4

我有一些代码在 C++ 中有一个动态类系统,它有一个名为 GetClassName() 的成员,这是一个可以想象的相当无害的名称。然而,当包含在一个带有 Windows 标头的大型项目中时,一切都乱了套。显然,Windows 使用了 #define GetClassName(GetClassNameA 或 GetClassNameW),它搞砸了一切,我的虚拟调用树变得一团糟,让我在黑暗中愚蠢的编译器调试中浪费了一天,试图找出问题所在。

因此,除了我在诅咒微软为#define 使用如此可怕的容易冲突的名称(我的意思是应该诚实地为此开枪!)之外,我要求 3 个目的。

  1. GetClassName() 的另一个好名字是什么?
  2. 有没有办法解决这个问题,所以将来我的代码库的其他开发人员不会遭受类似的命运
  3. 当其他人遇到这种类似莫名其妙的错误时,为了后代
4

4 回答 4

6
  1. ClassGetName()
  2. #undef GetClassName
  3. WinAPI 是一个 C API。没有命名空间。其他一些平台试图通过为所有符号名称添加前缀来缓解这种情况,但最终也分崩离析。最好的选择:如果您编写的代码不依赖于 Windows 平台 SDK 标头,那么不要#include使用.
于 2009-02-24T02:50:24.967 回答
4

我会重命名该方法。

当然可以说

#include <windows.h>
#undef GetClassName

但它并不干净,代码的用户在调用win32函数时记得写::GetClassNameW。

可以在他的类中提供 GetClassNameA 和 GetClassNameW 方法,但这很丑陋。

我看到两种方法:延长或缩短名称:)

1)为子系统中的所有功能添加前缀,fe TI_(用于类型信息):

TI_GetClassName() 
TI_GetBaseClass() 
TI_IsDerivedFromClass()
etc  

2)或将它们放入一些 IClass 接口中

interface IClass {
GetName();
GetBase(); 
IsDerivedFrom();
etc

并从单个方法返回该接口,
以便 GetClassName() 变为

GetClass()->GetName()
于 2009-02-24T05:20:10.517 回答
2

GetWindowClassName 也许?实际上,GetClassName 对这个 API 来说并不是一个坏名字,因为它与窗口类有关。真正的问题是它是一个 C API 声明,而 C 声明无法引入一个不会污染全局命名空间的可重用声明。

这更像是 C 语言的失败,而不是微软。

于 2009-02-24T02:51:58.660 回答
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 和 setter 命名为“GetX()”和“SetX()”,但更喜欢依赖重载机制并使用“xtype X() const”作为 getter 和“void X(xtype newval)” “对于二传手。您的里程可能会有所不同,但我发现它更清晰,并且 get/set 从参数中显而易见。显然,如果您使用默认参数,则必须小心。

祝你好运!

于 2009-02-24T03:03:40.737 回答