我有一些代码在C ++中有一个动态类系统,它有一个名为GetClassName()的成员,一个人们可以想象的无害的名字。然而,当包含在一个带有Windows标题的大型项目中时,所有地狱都会崩溃。显然,Windows使用#define GetClassName(GetClassNameA或GetClassNameW)搞砸了所有东西,我的虚拟调用树变得一团糟,让我在黑暗中愚蠢的编译器调试中失去了一天,试图弄清楚出了什么问题。
除此之外,我诅咒微软使用这样一个非常容易冲突的#define名称(我的意思是有人应该诚实地为此拍摄!)我要求3个目的。
答案 0 :(得分:5)
ClassGetName()
#undef GetClassName
#include
他们。 答案 1 :(得分:2)
GetWindowClassName也许?实际上,GetClassName不是这个API的坏名称,因为它与窗口类有关。真正的问题是它是一个C API声明,C声明无法引入一个不会污染全局命名空间的可重用声明。
这更像是C语言的失败而不是微软。
答案 2 :(得分:2)
Windows API充满了带有干净名称的宏,这些名称扩展为函数名称,后缀表示ASCII / UTF-16,具体取决于构建选项。如果他们用“W32”或类似的东西(OS X上的一个“NS”)作为前缀,那将是很好的,但他们选择不是为了保持API“干净”。
由于更改代码比使用API要容易得多,因此以下是一些建议:
1)学习Windows API(它实际上并不是那么大!),或者至少熟悉MSDN,以便在遇到无法解释的程序流时查找名称冲突。
2)在代码中使用显式范围解析(MyClass :: GetClassName())。不幸的是,这会破坏虚函数调度,所以要小心。
3)在代码中使用不同的命名约定。 MS总是使用CamelCase,所以如果你选择其他约定(get_class_name(),getClassName()等),你不会发生冲突。
4)就个人而言,我讨厌命名我的getter& setters“GetX()”和“SetX()”,但更喜欢依赖重载机制并对getter使用“xtype X()const”,对setter使用“void X(xtype newval)”。你的里程可能会有所不同,但我发现它更清洁了。从参数中可以看出get / set是显而易见的。显然,如果你使用默认参数,你必须要小心。 祝你好运!答案 3 :(得分:2)
我会重命名该方法。
当然可以说
#include <windows.h>
#undef GetClassName
但它不干净,一个人的代码用户应该记得在调用win32函数时写:: GetClassNameW。
可以在他的班级中提供GetClassNameA和GetClassNameW方法,但这很简单。
我看到两种方法:延长或缩短名称:)
1)为子系统中的所有函数添加前缀,例如TI_(对于类型信息):
TI_GetClassName()
TI_GetBaseClass()
TI_IsDerivedFromClass()
etc
2)或将它们放入某些IClass接口
interface IClass {
GetName();
GetBase();
IsDerivedFrom();
etc
从单一方法返回该接口,
以便GetClassName()成为
GetClass()->GetName()