当我声明并初始化一个const对象时。
// ConstClass.h
class ConstClass
{
};
const ConstClass g_Const;
两个cpp文件包含此标题。
// Unit1.cpp
#include "ConstClass.h"
#include "stdio.h"
void PrintInUnit1( )
{
printf( "g_Const in Unit1 is %d.\r\n", &g_Const );
}
和
// Unit2.cpp
#include "ConstClass.h"
#include "stdio.h"
void PrintInUnit2( )
{
printf( "g_Const in Unit2 is %d.\r\n", &g_Const );
}
当我构建解决方案时,没有链接错误,如果g_Const是非const基本类型,你会得到什么!
PrintInUnit1()和PrintInUnit2()表明在两个编译单元中有两个独立的“g_Const”具有不同的地址,为什么?
==============
我知道如何修复它。(使用extern关键字进行声明,并在一个cpp文件中定义它。)
我想知道为什么我在这个样本中没有得到redfined链接错误。
答案 0 :(得分:9)
https://stackoverflow.com/a/6173889/1508519
命名空间范围内的const变量具有内部链接。所以他们是 基本上两个不同的变量没有重新定义。
3.5 / 3 [basic.link]:
具有命名空间范围(3.3.5)的名称具有内部链接(如果是)
的名称- 一个对象,参考,函数或函数模板 显式声明为static或,
- 显式声明为const的对象或引用 显式声明extern或以前声明有外部 连锁;或
- 匿名工会的数据成员。
如果您希望它具有外部链接,请使用extern
。
如另一个答案所述,头文件只是粘贴在cpp文件中。两个cpp文件中都包含相同的头文件,但它们是单独的翻译单元。这意味着变量的一个实例与另一个实例不同。另一方面,让编译器知道您已在其他地方定义了变量,请使用extern
关键字。这确保了翻译单元之间只共享一个实例。但是extern const Test test
只是一个声明。你需要一个定义。只要在某个cpp文件中定义了一次就定义它并不重要。您可以根据需要多次声明它(这样可以方便地将其放在头文件中。)
例如:
Constant.h
class Test
{
};
extern const Test test;
Unit1.cpp
#include "Constant.h"
#include <iostream>
void print_one()
{ std::cout << &test << std::endl; }
Unit2.cpp
#include "Constant.h"
#include <iostream>
void print_two()
{ std::cout << &test << std::endl; }
的main.cpp
extern void print_one();
extern void print_two();
int main()
{
print_one();
print_two();
}
Constant.cpp
#include "Constant.h"
const Test test = Test();
生成文件
.PHONY: all
all:
g++ -std=c++11 -o test Constant.cpp Unit1.cpp Unit2.cpp main.cpp
答案 1 :(得分:5)
因为您将变量定义放在头文件中。包含头文件就像用文件内容替换它一样。所以,第一个文件:
// Unit1.cpp
#include "ConstClass.h" // this will be replace with the content of ConstClass.h
#include "stdio.h"
void PrintInUnit1( )
{
printf( "g_Const in Unit1 is %d.\r\n", &g_Const );
}
将成为(在编译之前的预处理阶段之后):
// Unit1.cpp
// ConstClass.h
class ConstClass
{
};
const ConstClass g_Const;
//this line is replaced with the content of "stdio.h"
void PrintInUnit1( )
{
printf( "g_Const in Unit1 is %d.\r\n", &g_Const );
}
第二个文件是:
// Unit2.cpp
// ConstClass.h
class ConstClass
{
};
const ConstClass g_Const;
//this line is replaced with the content of "stdio.h"
void PrintInUnit2( )
{
printf( "g_Const in Unit2 is %d.\r\n", &g_Const );
}
正如您所看到的,每个文件都有单独的变量g_Const
(这只是针对您的代码的情况,可能根本没有像宏一样的变量,请参阅我上一段中的解释)。 / p>
如果你想要的不是变量的定义,而只是头文件中的声明,你应该在头文件中使用extern
关键字:
extern const ConstClass g_Const;
然后,您可以将g_Const
变量的定义放在ConstClass.c
您的代码中有一些问题:
g_Const
定义中没有分配常量值,除非您需要默认值(0),否则必须在定义中为其指定一个常量值。const
变量的地址。这实际上迫使编译器在堆栈中创建变量。如果你不接受地址,它可能能够推断出在C中表现得像宏的编译时间数字(你可以直接将幻数放在使用const
变量的代码中)。