gpt4 book ai didi

C++使用数组中的类执行函数

转载 作者:行者123 更新时间:2023-11-28 00:03:02 28 4
gpt4 key购买 nike

我需要能够通过在数组中查找函数指针来调用作为类成员的函数。这个类将有子类做同样的事情,但如果他们不能资助这个功能,就会调用父类。为了简单起见,我删掉了大部分代码。剩下的内容如下所示。

最终的考验是创造:

1) Mammal : public Animal
1.1) Cat : public Mammal
1.2) Dog : public Mammal
2) Reptile : public Animal
2.1) Bird : public Reptile

我想尽可能干净地构建它,这样 Bob Martin 叔叔就会对我微笑。现在,我认为他只会刺激我一下,所以任何重构它以使其变得更好的帮助都将不胜感激。

class Animal {
public:
#define CMD_EAT 1
#define CMD_SLEEP 2
#define CMD_MAKENOISE 3

private:
const int _actions;
const char* _name;

public:
// Define a pointer to a function within this class that takes
// an INT as its argument
typedef void(Animal::*animalFunc)(int);

private:
// Define an array of pointers to action functions
animalFunc _actionPointers[]; //<<< COMPILE ERROR: "incomplete type is not allowed"

// Define an array of action names
char* _animalActions[];

public:
Animal(int actions, char* name) : _actions(actions), _name(name) {
_actionPointers[_actions] = NULL;
_animalActions[_actions] = NULL;
registerCommands();
}

// Define an array of pointers to action functions
//animalFunc animalCommands[MAX_ANIMAL_CMD];

// Register all commands supported by this class
virtual void registerCommands() {
registerCommand(CMD_EAT, "EAT", &Animal::eat);
registerCommand(CMD_SLEEP, "SLEEP", &Animal::sleep);
registerCommand(CMD_MAKENOISE, "MAKE NOISE", &Animal::makeNoise);
}

void registerCommand(int code, char* action, void (Animal::*animalFunc)(int)) {
_animalActions[code - 1] = action;
_actionPointers[code - 1] = animalFunc;
}

void exec(int code, int value) {
Serial.print("Executing ");
Serial.print(code);
*(this->_actionPointers[code])(value); //<<< THIS DOESN'T COMPILE
}

const char* getName() {
return _name;
}

// base class methods
virtual void eat(int times) {}

virtual void sleep(int times) {}

void makeNoise(int times) {}
};

void main() {
// Step 1: Create pointer to an instance of an animal object
Animal *pAnimal = new Animal(3, "ANIMAL");
pAnimal->exec(CMD_EAT, 1);
pAnimal->exec(CMD_SLEEP, 1);
}

我遇到了两个无法解决的编译错误。它们在代码中突出显示。

最佳答案

可以做的第一件事是用枚举替换 #define,并添加总命令数。

#define CMD_EAT             1
#define CMD_SLEEP 2
#define CMD_MAKENOISE 3

成为

enum {
CMD_EAT
, CMD_SLEEP
, CMD_MAKENOISE
, COMMAND_COUNT
};

接下来,我们应该确保代码是常量正确的。由于我们使用的是字符串常量,因此所有字符串变量和函数参数都应该是 char const* 而不是 char*

在此之后,我们可以将函数指针和名称组合在一个结构中,因为它们属于同一类。请注意,由于我们有成员函数指针的 typedef,我们可以使用它。

struct command_info
{
animalFunc handler;
char const* name;
};

因为我们现在知道编译时的命令数量,并且我们有上面的结构,我们可以有一个固定大小的数组:

command_info _commands[COMMAND_COUNT];

我们还可以从构造函数中删除 actions 参数。

因为我们有一个固定大小的数组,所以在访问数组之前验证索引很重要:

if (code < COMMAND_COUNT) { //...

接下来,你有虚方法,所以你的类也应该有一个虚析构函数:

virtual ~Animal() {}

我们接近尾声 -- 接下来是您如何处理 invoke the member function pointer 的问题.正确的方法(考虑到上述修改)是:

(this->*_commands[code].handler)(value);

最后,您在程序结束时泄漏了内存。

delete pAnimal;

不过,资源管理最好还是用RAII。由于您使用的是 AVR 并且没有可用的标准 C++ 库,因此您可以定义一个简单的句柄类,类似于

struct animal_ptr {
animal_ptr(Animal* a) : ptr(a) {}
~animal_ptr() { delete a; }
Animal* ptr;
}

完成修改后的代码

注意:我注释掉了涉及 Serial 的行,这样我就可以在没有它的情况下进行编译。

class Animal 
{
public:
enum {
CMD_EAT
, CMD_SLEEP
, CMD_MAKENOISE
, COMMAND_COUNT
};

// Define a pointer to a function within this class that takes
// an INT as its argument
typedef void(Animal::*animalFunc)(int);
struct command_info
{
animalFunc handler;
char const* name;
};

public:
Animal(char const* name)
: _name(name)
{
registerCommands();
}

// Register all commands supported by this class
virtual void registerCommands() {
registerCommand(CMD_EAT, "EAT", &Animal::eat);
registerCommand(CMD_SLEEP, "SLEEP", &Animal::sleep);
registerCommand(CMD_MAKENOISE, "MAKE NOISE", &Animal::makeNoise);
}

void registerCommand(int code, char const* action, animalFunc fn) {
if (code < COMMAND_COUNT) {
_commands[code].name = action;
_commands[code].handler = fn;
}
}

void exec(int code, int value) {
if (code < COMMAND_COUNT) {
//Serial.print("Executing ");
//Serial.print(code);
(this->*_commands[code].handler)(value);
}
}

char const* getName() {
return _name;
}

// base class methods
virtual void eat(int times) {}

virtual void sleep(int times) {}

void makeNoise(int times) {}


private:
char const* _name;

// Define an array of pointers to action functions
command_info _commands[COMMAND_COUNT];
};

int main() {
// Step 1: Create pointer to an instance of an animal object
Animal *pAnimal = new Animal("ANIMAL");
pAnimal->exec(Animal::CMD_EAT, 1);
pAnimal->exec(Animal::CMD_SLEEP, 1);
delete pAnimal;
}

Sample on Coliru

关于C++使用数组中的类执行函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37490956/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com