c++ - #define 类外宏
问题描述
我不太明白这里宏的用法:
在 Dog.cpp 中,在类范围之外有这个:
BEGIN_SETPARAM_MAP(Dog)
MAP_SETPARAM(eParam_Macro_Eat, Eat)
MAP_SETPARAM(eParam_Macro_Walk, Walk)
MAP_SETPARAM(eParam_Macro_Sleep, Sleep)
END_GETPARAM_MAP(Dog)
在 Animals.h 中有一个宏定义,也可以在 Animal 类范围之外找到:
class Animal
{
protected:
HRESULT MapSetParamHandler(ULONG paramId, ParamValueHandler handler);
virtual void SetupSetParamMap(void) {}
};
#define BEGIN_SETPARAM_MAP(className) void className::SetupSetParamMap(void) {typedef className ThisClass;
#define MAP_SETPARAM(paramId, handler) MapSetParamHandler(paramId, static_cast<ParamValueHandler>(&ThisClass::handler));
#define END_SETPARAM_MAP(className) }
我不明白这实际上是如何工作的。为什么允许在类外重新定义方法SetupSetParamMap()
?如果是这样,这会覆盖 Animal 类的实现吗?
我不知道上面的代码如何编译得很好。
我尝试创建一个更简单的示例,但出现语法错误:
// Example program
#include <iostream>
#include <string>
class Animal
{
public:
void cuddle()
{
std::cout << "Cuddle" << std::endl;
}
};
class Dog : public Animal
{
public:
void bark()
{
std::cout << "Bark" << std::endl;
cuddle();
}
virtual void sleep(){}
};
#define BEGIN_SETPARAM_MAP(className) void Dog::sleep() \
{ \
std::cout << "sleep" << std::endl; \
}
BEGIN_SETPARAM_MAP(Dog);
int main()
{
Dog dog;
dog.bark();
dog.sleep();
return 0;
}
这是错误:
25:44: error: redefinition of 'void Dog::sleep()'
30:1: note: in expansion of macro 'BEGIN_SETPARAM_MAP'
22:18: note: 'virtual void Dog::sleep()' previously defined here
帮助,任何人?
解决方案
我不明白这实际上是如何工作的。为什么允许在类外重新定义方法 SetupSetParamMap()?
该代码之所以有效,是因为它没有定义方法 Animal::SetupSetParamMap。宏的作用是允许您为另一种对象类型实现 SomeDerivedAnimalType::SetupSetParamMap。如果您尝试执行:BEGIN_SETPARAM_MAP(Animal),那么现在您将遇到 Animal::SetupSetParamMap 的重新定义错误。但是 BEGIN_SETPARAM_MAP(Sheep) 不会引起问题。
对于第二个代码示例,编译器错误是非常不言自明的......(你清楚地已经识别出来了!)
class Dog : public Animal
{
public:
void bark()
{
std::cout << "Bark" << std::endl;
cuddle();
}
virtual void sleep(){} ///< I AM THE IMPLEMENTATION OF Dog::sleep
};
/// I AM ALSO THE IMPLEMENTATION OF Dog::sleep, and therefore an error...
#define BEGIN_SETPARAM_MAP(className) void Dog::sleep() \
{ \
std::cout << "sleep" << std::endl; \
}
这是一个稍微简单的示例,让您了解一下;)
class Animal
{
public:
/// I need to be implemented for each animal
/// It's boiler-plate repetition, so lets macro this
virtual void speak() = 0;
};
// use within the class definition to add capabilities
#define CAN_SPEAK(animalType) void speak() override;
// use to implement the boiler plate code of the method
#define MAKE_SPEAK(animalType, noise) void animalType::speak() \
{ \
std::cout << noise << std::endl; \
}
// here's a dog that says woof
class Dog : public Animal
{
public:
CAN_SPEAK(Dog)
};
MAKE_SPEAK(Dog, "woof")
// ... and a sheep that says baa
class Sheep : public Animal
{
public:
CAN_SPEAK(Sheep)
};
MAKE_SPEAK(Sheep, "baa")
int main()
{
std::vector<Animal*> animals;
animals.push_back(new Dog);
animals.push_back(new Sheep);
for(auto animal : animals)
{
animal->speak();
}
/* yes, I should be freeing the memory here... */
return 0;
}
推荐阅读
- php - Laravel 7 向已验证的中间件添加值检查?
- excel - 从各种其他文档中提取组织成员信息
- google-sites - 如何将包含代码的部分包含到 Google 协作平台中?
- javascript - 如何在 HTML 文件中包含 CDN
- flutter - 根据用户的位置向特定用户发送通知
- sql - 在一段时间内应用/保持状态
- node.js - 无法调试节点,使用 nodemon、dockerfile 和 docker-compose
- python - 如何将数据从 Jetson nano 发送到 Arduino?
- python - 将具有 100k 行的工作簿的工作表复制到当前工作簿的速度提高 10 倍
- python - Python kubernetes pod watch 状态