2012-01-27 98 views
1

该代码给出很多是全球性的常量具有内部范围,这是默认的静态在C会产生错误++常量和全球

// Foo.cpp 
const int Foo = 99; 

// Main.cpp 
extern const int Foo; 
int main() 
{ 
    cout << Foo << endl; 
    return 0; 
}  

原因。

解决方案是: -

//Foo.h 
    extern const int Foo; 

    // Foo.cpp 
    #include "Foo.h" 
    const int Foo = 99; 

    // Main.cpp 
    #include "Foo.h" 
    int main() 
    { 
     cout << Foo << endl; 
    } 

我常想,EXTERN被用来告诉内存为indentifer已经在其他文件中的某个地方分配的编译器。
在上面的代码中应用相同的逻辑,任何人都可以解释这里发生了什么,或者extern在C++中有不同的含义?
enter link description here
还要考虑这个网页它毁了我所有的直觉..

回答

7

如果我们要声明只能在全局常量(不static)? extern如何帮助做到这一点?

A const对象声明为extern限定符具有外部链接。
因此,如果您想跨多个翻译单元使用const,请在其中添加extern限定符。

尽管默认情况下全局变量具有外部链接,但为什么默认情况下const全局链接具有内部链接?

参考:
C++ 03标准附录C兼容性C.1.2条款3:基本概念

变化:是显式声明的常量,而不是文件范围的名称明确地声明为extern,具有内部连接,而在C中将具有外部连接

理由:因为const对象可以用作编译时间val在C++中,这个特性促使程序员为每个const提供显式的初始值。此功能允许用户将常量对象放在包含在许多编译单元中的头文件中。


通过以下简单的规则避免混乱:

缺省情况下联动为常量符号外部对非const符号和静态的(内部)。

3

在此提醒,使得它清楚我们正在谈论:

int const a;   // illegal 
int const a = 42;  // definition, internal linkage 
extern int const a;   // declaration, external linkage 
extern int const a = 42; // definition , external linkage 

注意,如果没有const,上述前两个声明是一个具有外部链接都 定义。这只是正交,并不是很直观,但这是现行规则所说的。

与给予一个const外部连接的问题在于,只能有一个 具有外部链接的对象的定义,并且与一个 例外,只有定义可以具有一个初始化。这意味着对于具有外部链接的const的 ,只能在一个 翻译单元中看到实际值(如果 const用于常量表达式,则必需的实际值)。这可能是默认情况下给予const 内部链接的动机。

当然,这不会导致模板问题的结束,理论上至少 ;下面的头有未定义的行为,如果它是 包括在多于一个翻译单元:

#include <std::vector> 

int const fixedValue = 42; 
inline void insertFixedValue(std::vector<int>& dest) 
{ 
    dest.push_back(fixedValue); 
} 

的标准说不仅必须内联函数和模板具有 令牌相同的序列,但是,所有的符号的必须将 绑定到每个翻译单元中的相同对象,或者存在违反 的一个定义规则。并且由于fixedValue没有外部连接,因此每个翻译单元中都有一个唯一的实例。 (有 异常如果符号指const对象有 立即左值到右值转换。由于 std::vector<int>::push_back然而通过引用接受其参数, 没有即时左值到右值的转换,我们得到了一个未定义 行为)

和当然,任何人只要有一个模板:

template <int& r> ... 

不能实例化它。

内部联动的原因当然是历史性的。今天, 编译器必须能够支持诸如:

struct X 
{ 
    static int const a = 42; // declaration!!!, external linkage 
}; 

和功能的各种重复定义。这将是 比较琐碎延长,允许在 声明初始化在命名空间范围类变量的规则,给 类似:

int const a;    // illegal 
int const a = 42;   // definition, external linkage 
extern int const a;   // declaration, external linkage 
extern int const a = 42; // declaration, external linkage 

这将恢复正交性(即使它需要额外的输入) 。它 也将打破几乎所有现有的代码。

另一种方法是治疗const变量定义 完全一样的功能模板今天对待:你可以有多个 定义,但它们都必须是相同的。这大概会避免 大部分(如果不是全部的话)代码破坏。

+0

'extern const a; '不是有效的C++,我不认为。你需要像'extern const' ** int **'a;'你在第一个突出显示的块中有错误,但是在最后一个错误。 – 2014-08-06 19:25:13

+0

@RobertCrovella今天我认为它甚至不是有效的C(如果它是有效的,那肯定是不好的做法)。我修复了它。 – 2014-08-07 08:23:09