为什么在头文件中定义`const int`时没有重复的定义错误?

托尼·白

抱歉,是否曾经有人问过。我搜索了互联网,但没有找到答案。

说我有一个文件Common.hA.cppB.cpp包含Common.h

如果我想有一个全球性const char *Common翻译单元,我必须说externCommon.h,并在定义它Common.cpp否则,如果仅const char * MSG = "Hello World";在中定义,则在编译期间Common.h会出现duplicate symbol错误。

但是,如果我仅Common.h使用如下语句定义全局const int,const int CONSTANT = 10;则代码将编译而不会出现重复的符号错误,并且一切正常。

我对为什么会这样感到困惑。在我看来,上面两个示例之间的唯一区别是类型,我认为这没有什么区别。为什么我得到C字符串的重复符号错误,而不是整数?

假设main.cppA.hB.hA.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();
}

现在,假设我们使用command进行编译g++ main.cpp A.cpp B.cpp Common.cpp -std=c++14

如果我们做Common.hCommon.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 *为什么使指针const起作用?另外,在这种情况下,此解决方案与我上面提供的解决方案(在此我们将字符串改为extern并拆分定义/声明)之间有什么区别?为什么这两种方法都能解决编译错误,并且两种方法之间有什么区别?

我还注意到,如果我const int变成just int,那么我会duplicate symbol再次得到错误。我觉得这背后的原因与上述问题的答案有关。为什么会这样呢?

安德烈亚斯(Andreas H.)

这是C和C ++的差异之一。

在C ++中,const变量是隐式的static,即仅对当前翻译单元可见。在C中,它extern对于整个程序是隐式可见的(这也是C和C ++中其他非const声明的默认值)。

这解释了您的观察。

注意:const char *p变量声明不是const变量。这意味着它指向一个const变量(即*p无法修改),但p其本身不是const因此,这里的行为是不同的。const char * const p将是一个const声明。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么可以在头文件中定义类?

为什么不建议在头文件中定义宏?

头文件中const变量的多个定义

为什么在头文件中定义函数会产生多个定义错误,而不是类?

为什么Libclang无法获得在头文件中定义的函数的定义?

未定义参考-链接时为什么在头文件中找不到某些方法?

为什么C头文件中的全局变量定义有效?

为什么我不能在头文件中定义全局函数?

为什么必须内联在类外部(但在头文件中)定义的类成员函数?

为什么不能使用#pragma once 在头文件中定义静态成员

我无法弄清楚为什么在头文件中调用方法时出现未定义的引用问题

头文件中定义的函数的重复符号

为什么在cpp文件中定义了非int const静态变量?

头文件中定义的函数的原型错误

PHP7 const 在条件(if)中的 require(外部文件)中定义正在工作 - 为什么?

什么是“ Class ClassName;” 放在其他类定义的头文件中时意味着什么?

C:我们为什么要包含声明但未定义的头文件?

为什么需要在Objective-C的头文件中使用“外部静态”来定义常量?

为什么某些Linux头文件定义了一个在声明后返回0的函数?

避免在头文件中定义模板

在头文件中定义类是否正确?

检索头文件中定义的结构列表

C头文件中的外部定义常量

Bindgen跳过C ++头文件中的定义

头文件中的函数未定义

C-头文件中的结构定义

为什么标准库在.c文件而不是头文件中具有#include <...>

Elixir-为什么这些重复的头文件没有编译器警告?

当我在 Python 类中定义局部函数时,为什么会出现“对象没有属性”错误?