我在使用Visual Studio 2010和C ++时遇到了一些奇怪的行为。 我有一个头文件,我在其中声明了一些全局常量
#ifndef CONSTANTS_H
#define CONSTANTS_H
#define WIN32_LEAN_AND_MEAN
// Macros...
#define SAFE_RELEASE(ptr) { if (ptr) { ptr->Release(); ptr = NULL } }
#define SAFE_DELETE(ptr) { if (ptr) { delete ptr; ptr = NULL; } }
// Constants...
const char* CLASS_NAME = "WinMain";
const char GAME_TITLE[] = "DirectX Window";
const int GAME_WIDTH = 640;
const int GAME_HEIGHT = 480;
#endif
我的问题来自以下一行:
const char* CLASS_NAME = "WinMain";
当它是这样的,我构建我的解决方案时,我得到以下2个错误:
error LNK1169: one or more multiply defined symbols found
和
error LNK2005: "char const * const CLASS_NAME" (?CLASS_NAME@@3PBDB) already defined in graphics.obj
现在很奇怪,因为一个'在文件中查找'并且我绝对不会在其他地方声明它,即没有重复的声明。
我应该将其更改为:
const char* const CLASS_NAME = "WinMain";
OR
const char CLASS_NAME[] = "WinMain";
编译得很好!但据我所知char* x
相当于char x[]
,而且我对指针和指向值强制执行'const-ness'的事实应该没有区别......或者是吗?
我对Windows平台上的C ++开发有点新意,所以非常感谢任何帮助!
答案 0 :(得分:6)
您错误的是您没有将常量声明为常量。在C ++语法(以及C语言)中,为了声明一个常量指针,你必须这样做
const char* const CLASS_NAME = "WinMain";
请注意,您的GAME_TITLE
,GAME_WIDTH
和GAME_HEIGHT
已正确声明为常量,这就是为什么它们不会给您带来任何麻烦。只有CLASS_NAME
声明不正确,即非常数。
默认情况下,C ++中的常量具有内部链接,这就是为什么你可以在头文件中定义它们而不违反一个定义规则。
答案 1 :(得分:5)
不要在标头中定义变量。当您在多个翻译单元中包含该标题时,您将拥有该定义的多个副本。
只有在那里声明变量(使用extern
),并在一个翻译单元中定义它们。
那说......对于内置类型的常量,可以对此规则进行例外处理,因为它们默认具有内部链接。
也就是说,这两个程序在功能上完全相同:
const int x = 42;
int main() {}
static const int x = 42;
int main() {}
这确保为每个翻译单元生成一个副本,完全避免此问题。
我认为对于数组也是如此。所以,当然,const
它会把你自己打倒。
但据我所知'char * x'相当于'char x []',
仅在功能参数列表中。在完全成熟的声明中,x
将采用从初始化程序确定的维度的数组类型。
答案 2 :(得分:1)
您收到错误,因为如果您将文件包含在多个编译单元中,则在每个单元中声明该名称的变量。编译不是问题,但是当链接器尝试链接时,会看到同一变量的多个定义。您可以使用const int
变量和const char GAME_TITLE[]
来解决此问题,因为它们具有静态链接,但对于字符串文字(基本上是char
数组),您将收到此错误。您应该能够使用extern