由于一个定义规则,在C或C++中不允许对全局变量进行多个定义。然而,在C++中,const全局变量可以在多个编译单元中定义,而不会出错。这与C.不同
为什么C++允许这样做,而C不允许?为什么与C相比,C++中常量全局变量的用法和行为与非常量全局变量有这种不同?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;
}
// Foo.cpp
const int Foo = 99;
// Main.cpp
const int Foo = 99;
命名空间作用域上的const
变量具有内部链接。所以它们基本上是两个不同的变量。没有重新定义。
来自@David的评论,3.5/3[基本链接]:
具有命名空间范围的名称(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;
}
我认为您询问的是基本原理,而不是允许这样做的特定语言规则。
这样做的理由是它使const
变量更易于使用。它给出了#define
的一个常用用法的类型替换。
您可以完全相同的方式使用const int max_count = 211;
,而不是#define MAX_COUNT 211
,例如共享头文件,而不必担心将一个定义放在哪里。
您不能合法更改const
对象的值,因此一个对象和多个具有相同值的对象之间没有明显区别。
由于您可以将const
对象的定义放在头文件中,因此编译器在编译阶段直接使用该值是很简单的,而不必将此类优化延迟到链接时间修复。
基本上,在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中,这并不存在,它们只是碰巧不可修改的变量。
看起来const实际上并没有生成外部符号。
为什么英国人拼写COLOUR,而美国人拼写COLOR
它们是来自同一基础的两种不同语言,但它们没有相同的规则。
C&C++是一样的。如果它们没有不同,它们就会被称为相同的东西。
我的解决方法是将其声明为:
static classfoo foo;
它在我的情况下起了作用。