为什么在C ++中而不是在C中允许对const全局变量进行多重定义?

时间:2011-05-30 08:19:45

标签: c++ c const one-definition-rule

由于One Definition Rule,C或C ++中不允许对全局变量进行多次定义。但是,在C ++中,const全局变量可以在多个编译单元中定义而没有错误。这与C中的不同。

为什么C ++允许这样做而C不允许?与C相比,为什么const全局的使用和行为在C ++中以这种方式与非const全局不同? C ++和C关于const的内容正在发生什么?

例如,这在C ++中是允许的,但在C:

中是错误的
// Foo.cpp
const int Foo = 99;

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

这对C来说很好,但C ++有问题:

// Foo.cpp
const int Foo = 99;

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

6 个答案:

答案 0 :(得分:27)

// Foo.cpp
const int Foo = 99;

// Main.cpp
const int Foo = 99;
命名空间范围内的

const变量具有内部链接。所以它们基本上是两个不同的变量。没有重新定义。

来自@ David的评论,3.5 / 3 [basic.link]:

  

具有命名空间范围的名称(3.3.5)   如果是名称,则具有内部链接   
的    - 对象,参考,功能或   明确的功能模板   声明静态或,
   - 一个对象或   显式声明的引用   const并且都没有明确声明   extern也没有声明过   外部联系;或
   - 数据成员   一个匿名工会。


在第二种情况下,你应该这样做(正确的方法):

//Foo.h
extern const int Foo; //use extern here to make it have external linkage!

// Foo.cpp
#include "Foo.h"
const int Foo = 99; //actual definition goes here

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

答案 1 :(得分:7)

我认为你要求的理由而不是具体的语言规则。

这样做的理由是它使const变量更容易使用。它为#define的一个常见用途提供了类型替换。

您可以以完全相同的方式使用#define MAX_COUNT 211,而不是const int max_count = 211;,例如共享头文件,无需担心在哪里放置一个定义。

您不能合法地更改const对象的值,因此在拥有一个对象和具有相同值的多个对象之间没有明显的区别。

由于您可以在头文件中定义const对象,因此编译器可以直接在编译阶段使用该值,而不必将此类优化延迟到链接时修复。

答案 2 :(得分:6)

基本上,在C ++中,const,非局部变量是真正的常量表达式,或constexpr。这允许很多东西,比如TMP。

const int five = 5;
int main() {
    int x[five];
    std::array<int, five> arr;
}

在C中,它们只是一个无法修改的变量。也就是说,

const int five = 5;
int main() {
    int x[five]; // Technically, this is a variable length array
}

完全等同于

int five = 5;
int main() {
    int x[five];
}

实际上,C ++将某些const变量提升为新类别constexpr,而在C中,这不存在,它们只是碰巧不可修改的变量。

答案 3 :(得分:3)

答案 4 :(得分:0)

为什么英国人拼写COLOR,而美国人拼写COLOR?

它们是来自同一基础的两种不同语言,但它们没有相同的规则。

C&amp; C&amp; C ++是一样的。如果他们没有什么不同,他们都会被称为同一件事。

答案 5 :(得分:-2)

我的解决方法是将其声明为:

static classfoo foo;

它适用于我的情况。