如果之前有人问过这个问题,我们深表歉意。我在网上查了一下,没有找到答案。
假设我有一个文件 Common.h
,并且 A.cpp
和 B.cpp
包含 Common.h
.
如果我想在 Common
翻译单元中拥有一个全局 const char *
,我必须在 Common 中将其设置为
,并在extern
.hCommon.cpp
中定义它。否则,如果我只是在 Common.h
中定义 const char * MSG = "Hello World";
,我会在编译期间收到 duplicate symbol
错误.
但是,如果我只是在 Common.h
中使用 const int CONSTANT = 10;
之类的语句定义一个全局 const int,那么代码编译时不会出现重复符号错误,一切正常。
我很困惑为什么会出现这种情况。在我看来,上面两个例子之间的唯一区别是类型,我认为这不应该有什么区别。为什么 C 字符串会出现重复符号错误,而整数却不会?
假设 main.cpp
、A.h
、B.h
、A.cpp
和 B。 cpp
如下所示:
// A.h
#pragma once
void f();
// A.cpp
#include "A.h"
#include "Common.h"
#include <iostream>
void f() {
std::cout << MSG << std::endl;
}
// B.h
#pragma once
void g();
// B.cpp
#include "B.h"
#include "Common.h"
#include <iostream>
void g() {
std::cout << CONSTANT << std::endl;
}
// main.cpp
#include "A.h"
#include "B.h"
int main()
{
f();
g();
}
现在,假设我们使用命令 g++ main.cpp A.cpp B.cpp Common.cpp -std=c++14
进行编译。
如果我们将 Common.h
和 Common.cpp
设为以下内容,则编译会失败并出现错误 duplicate symbol MSG
:
// Common.h
#pragma once
const char * MSG = "Hello World";
const int CONSTANT = 10; // defined in header file
// Common.cpp
// empty
但是,这可以编译:
// Common.h
#pragma once
extern const char * MSG;
const int CONSTANT = 10; // defined in header file
// Common.cpp
#include "Common.h"
const char * MSG = "Hello World";
我想知道为什么我们需要 extern 并分隔字符串的定义和声明,而不是 int。
有人建议将 C 字符串类型设置为 const char * const
而不是 const char *
。为什么使指针常量有效?另外,在这种情况下,这个解决方案和我上面提供的解决方案(我们用字符串 extern 代替并分割定义/声明)有什么区别?为什么这两种方法都能解决编译错误,方法之间有什么区别?
我还注意到,如果我将 const int
转换为 int
,那么我会再次收到 duplicate symbol
错误。我觉得这背后的原因与我上面问题的答案有关。为什么会这样?
最佳答案
这是C和C++的区别之一。
在 C++ 中,const
变量是隐式静态
的,即仅对当前翻译单元可见。在 C 中,它是隐式 extern
的,因此对整个程序可见(这也是 C 和 C++ 中其他非常量声明的默认设置)。
这解释了你的观察结果。
注意:变量的 const char *p
声明不是 const
变量。这意味着它指向一个const变量(即*p
无法修改),但p
本身不是const
.所以这里的行为是不同的。 const char * const p
将是一个 const 声明。
关于c++ - 为什么我在头文件中定义 `const int`时没有重复定义错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63840677/