常量variables不起作用

如果我在我的标题中定义我的常量variables像这样…

extern const double PI = 3.1415926535; extern const double PI_under_180 = 180.0f / PI; extern const double PI_over_180 = PI/180.0f; 

我得到以下错误

 1>MyDirectX.obj : error LNK2005: "double const PI" (?PI@@3NB) already defined in main.obj 1>MyDirectX.obj : error LNK2005: "double const PI_under_180" (?PI_under_180@@3NB) already defined in main.obj 1>MyDirectX.obj : error LNK2005: "double const PI_over_180" (?PI_over_180@@3NB) already defined in main.obj 1>MyGame.obj : error LNK2005: "double const PI" (?PI@@3NB) already defined in main.obj 1>MyGame.obj : error LNK2005: "double const PI_under_180" (?PI_under_180@@3NB) already defined in main.obj 1>MyGame.obj : error LNK2005: "double const PI_over_180" (?PI_over_180@@3NB) already defined in main.obj 

但如果我从标题中删除这些常量,并把它们放在包含这样的标题的文档…

 const double PI = 3.1415926535; const double PI_under_180 = 180.0f / PI; const double PI_over_180 = PI/180.0f; 

有用

有没有人有想法我可能做错了?

谢谢

问题是你在头文件中定义了外部链接的对象。 预计,一旦将这个头文件包含到多个翻译单元中,您将通过外部链接获得同一个对象的多个定义,这是一个错误。

正确的做法取决于你的意图。

(1)你可以把你的定义放到头文件中,但是要确保它们有内部连接。

在C中,这将需要一个明确的static

 static const double PI = 3.1415926535; static const double PI_under_180 = 180.0f / PI; static const double PI_over_180 = PI/180.0f; 

在C ++中, static是可选的(因为在C ++中const对象默认有内部链接)

 const double PI = 3.1415926535; const double PI_under_180 = 180.0f / PI; const double PI_over_180 = PI/180.0f; 

(2)或者你可以把非定义的声明放到头文件中,并把定义放入一个(也是唯一的)实现文件

文件中的声明必须包含一个显式的extern不是初始化器

 extern const double PI; extern const double PI_under_180; extern const double PI_over_180; 

一个实现文件中的定义应该如下所示

 const double PI = 3.1415926535; const double PI_under_180 = 180.0f / PI; const double PI_over_180 = PI/180.0f; 

(如果上述声明位于同一翻译单元中的定义之前,则定义中的显式extern是可选的)。

你会select哪种方法取决于你的意图。

第一种方法使编译器更容易优化代码,因为它可以在每个转换单元中看到常量的实际值。 但是从概念上讲,同时在每个翻译单元中都有单独的,独立的常量对象。 例如, &PI将在每个翻译单元中评估不同的地址。

第二种方法创build真正的全局常量,即由整个程序共享的唯一常量对象。 例如, &PI将在每个翻译单元中评估相同的地址。 但是在这种情况下,编译器只能看到一个且只有一个翻译单元的实际值,这可能会阻碍优化。

extern意味着variables的“真实”定义是在其他地方,编译器应该相信在链接时会挂钩。 与extern内联的定义是奇怪的,是什么是你的程序。 如果你想让它们成为extern ,只要在程序中的其他地方精确地定义它们即可

他们的extern存储类几乎肯定是你看到的问题的原因。 如果你删除它,代码可能会很好(至less在这方面)。

编辑:我只是注意到,你已经标记为C和C + +。 在这方面,C和C ++是非常不同的(但是从错误消息来看,你显然是编译为C ++,而不是C)。 在C ++中,您要删除extern ,因为(默认情况下) constvariables具有static存储类。 这意味着每个源文件(翻译单元)都将获得自己的“副本”variables,并且在不同文件中的定义之间不会有任何冲突。 既然你(可能)只使用这些值,而不把它们当作variables来处理,那么拥有多个“副本”不会伤害任何东西 – 它们都不会被分配存储空间。

在C中, extern是相当不同的,移除extern不会有什么真正的区别,因为它们默认是extern 。 在这种情况下,你确实需要在一个地方初始化variables,并在头文件中声明它们为extern。 或者,您可以添加默认情况下添加的static存储类,当/从标头中删除extern

它看起来像头文件被包含多次。 你需要加上警卫。

在每个头文件的顶部你应该有这样的东西:

 #ifndef MY_HEADER_FILE_NAME_H #define MY_HEADER_FILE_NAME_H ... // at end of file #endif 

如果您使用的是g ++或MSVC,那么您可以只添加:

 #pragma once 

在每个头文件的顶部,但这不是100%的便携式。

另外,你不应该在头文件中定义常量,只声明它们:

 // In header file extern const int my_const; // In one source file const int my_const = 123; 

下面有很多不正确的回答。 那些正确的是告诉你去除extern因为sellibitze在他的评论中也说了正确的。

因为这些被声明为const,所以在头文件中定义没有问题。 除非你试图把它的地址(一个指向const的指针),在这种情况下,它将使用static链接来实例化它,否则C ++会为内buildtypes内联一个const,然后你可能会在不同的模块中获得多个实例化,但除非你期望所有指向同一个const的指针具有相同的地址,这不是一个问题。

你需要在头文件中声明这些语句,然后在你的一个代码文件中定义它们。 如果你不把它们声明在任何地方,那么当它试图把声明和实际的定义联系起来的时候,会有一个链接错误。 您也可以使用#ifdef语句在头文件中定义一个定义。

确保它们是在需要它们的每个人所包含的标题中声明的,并确保它们只被定义一次。

雅各

如果要在头文件中定义常量,请使用static const 。 如果你使用extern ,链接器是正确的抱怨多个定义,因为每个包含源文件将提供内存的variables,如果你分配一个值。

问题是你正在初始化头文件中的variables; 这将创build一个定义声明,在包含该头文件的每个文件中重复该定义声明,从而产生多重定义错误。

你需要在头文件中有一个定义的声明(没有初始化),并把定义声明放在一个实现文件中。

在头文件中声明全局常量会导致包含这个hader的每个编译单元将拥有自己的具有相同名称的全局定义。 那么链接器不喜欢那样。

如果你真的需要这些头,那么可能你应该声明它们是静态的。

一个古老的问题的确如此,但是却没有一个有用的答案。

有可能欺骗MSVC接受头中的静态常量,只需将它们包装在“虚拟”类模板中即可:

 template <typename Dummy = int> struct C { static const double Pi; }; template <typename Dummy = int> const double C<Dummy>::Pi = 3.14159; 

现在,可以从别处访问C <> :: PI。 没有重新定义的抱怨; 常量可以在每个编译单元中直接访问,而不需要花费时间优化。 macros可以推出进一步美化这种方法(即使macros是邪恶的)。