我有一个预处理器宏,它根据宏参数生成函数和变量。
使用A,B随后调用宏,宏将生成类似
的内容Inst* AActivate() { ... }
bool Atemp;
Inst* BActivate() { ... }
bool Btemp;
由于宏是在头文件中定义的,因此我收到链接器错误,通知我已定义的符号。 我正在使用#pragma一次,但我想问题在于在头文件中实现函数。
这是宏:
#define REGISTER(ns, id, type) \
Inst* type##Activate() { return new type(); }\
bool type##temp = RegisterType(ns << 8 | id, &type##Activate);
现在我想知道如何处理这些问题。 我的第一个想法是使用了一些#define-Guards,但显然这需要嵌套的#defines,这在C ++中是不可能的。 我读到了一个可能的提升解决方案,但不幸的是,我无法使用这些库。
有什么想法吗?
提前谢谢你......
答案 0 :(得分:3)
您的宏在标头中生成函数 definitions ,与任何普通函数一样,如果标头包含在多个转换单元中,则标头中的非内联函数会违反ODR。所以只需将生成的函数内联。
对于全局变量,ODR也适用,您必须将它们声明为static或const以获取内部链接。这反过来将为您提供变量的多个独立实例,每个转换单元一个包含标头。无论如何,全局变量被认为是不好的风格,所以也许你应该想到别的东西。
答案 1 :(得分:0)
使用.cpp文件中的宏或内联函数。使用#pragma一次并没有什么帮助,因为这只会阻止每个.cpp文件包含多个标头。编译多个.cpp文件时,会多次定义函数。
答案 2 :(得分:0)
你标记了C和C ++,你真的应该决定使用哪一个。
如果您的函数定义为inline
,那么这样的事情只能在两种语言中起作用。然后,您必须有两个宏,一个用于内联定义,您将在每个头文件中调用该宏来查看该函数。
此外,您必须拥有第二个宏,该宏仅在一个.c或.cpp文件中调用,以便为您执行“实例化”。对于C或C ++,语法可能略有不同。
在C中,它应该类似于
#define REGISTER(ns, id, type) \
inline Inst* type##Activate() { return new type(); } \
extern bool type##temp
#define INSTANTIATE(ns, id, type) \
Inst* type##Activate(); \
bool type##temp = RegisterType(ns << 8 | id, &type##Activate)