8

我在使用 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";

或者

const char CLASS_NAME[] = "WinMain";

它编译得很好!但据我所知char* x,它等同于char x[],并且我在指针和指向的值上都强制执行“常量”这一事实应该没有什么区别......或者是吗?

我对 Windows 平台上的 C++ 开发有点陌生,因此将不胜感激任何帮助!

4

3 回答 3

7

您的错误是您没有将常量声明为常量。在 C++ 语法中(以及在 C 中)为了声明一个常量指针,你必须这样做

const char* const CLASS_NAME = "WinMain";

请注意,您的GAME_TITLE,GAME_WIDTHGAME_HEIGHT被正确声明为常量,这就是它们不会给您带来麻烦的原因。只有CLASS_NAME被错误地声明,即作为非常量。

默认情况下,C++ 中的常量具有内部链接,这就是为什么您可以在头文件中定义它们而不会违反单一定义规则的原因。

于 2012-12-07T23:35:33.497 回答
5

不要在标题中定义变量。当您在多个翻译单元中包含该标题时,您将拥有该定义的多个副本。

仅在此处声明变量(使用extern),并在一个翻译单元中精确定义它们。

也就是说......对于内置类型的常量,可以对这个规则进行例外处理,因为默认情况下它们具有内部链接。

也就是说,这两个程序在功能上是相同的:

const int x = 42;
int main() {}

static const int x = 42;
int main() {}

这可确保为每个翻译单元生成一份副本,从而完全避免该问题。

认为数组也是如此。所以,当然,const它把自己击倒。


但据我所知 'char* x' 等价于 'char x[]',

仅在函数参数列表中。在一个成熟的声明中,x将采用由初始化程序确定维度的数组类型。

于 2012-12-07T22:52:10.950 回答
1

您会收到错误消息,因为如果您将文件包含在多个编译单元中,您将在每个单元中声明该名称的变量。编译不是问题,但是当链接器尝试链接时,它会看到同一个变量的多个定义。你可以用const int变量来解决这个问题,const char GAME_TITLE[]因为它们有静态链接,但是对于字符串文字(本质上是char数组)你会得到这个错误。您应该能够使用extern

于 2012-12-07T22:52:42.437 回答