【问题标题】:Constant definition in multiple files多个文件中的常量定义
【发布时间】:2015-04-04 18:53:50
【问题描述】:

我正在阅读“C++ 入门加”。第9章讲了C++和C在处理const修饰符时的区别:

“在 C++(但不是 C)中,const 修饰符会稍微改变默认存储类。而全局变量默认具有外部链接,而 const 全局变量默认具有内部链接。

...

如果全局 const 声明与常规变量一样具有外部链接,这将是一个错误,因为您只能在一个文件中定义全局变量。也就是说,只有一个文件可以包含过程声明,而其他文件必须使用 extern 关键字提供引用声明。”

我尝试使用以下程序测试此声明:

文件.h:

using namespace std;

const char *constant = "Magic";

file1.cpp

#include <iostream>
#include "file.h"
extern void file2();
int main(){
  cout << "constant = " << constant << endl;
  file2();
}

file2.cpp

#include <iostream>
#include "file.h"

void file2(){
  cout << "file2 constant = " << constant << endl;
}

生成文件:

CFLAGS = -Wall -g
INCLUDE = file.h
src = file2.cpp file1.cpp

all: $(src) $(INCLUDE)
  g++ $(CFLAGS) -o file $(src)

clean:
  rm -f file

当我做时,我收到以下错误消息:

g++ -Wall -g -o file file2.cpp file1.cpp
/tmp/ccdl16Tw.o:(.data+0x0): multiple definition of `constant'
/tmp/ccA3ZEHa.o:(.data+0x0): first defined here
collect2: error: ld returned 1 exit status
make: *** [all] Error 1

gcc 版本 4.8.2

更新:

如果我这样做

 char* const constant = "Magic";

然后make会给我这个警告:

g++ -Wall -g -o 文件 file2.cpp 文件1.cpp

In file included from file2.cpp:2:0:
file.h:3:24: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
 char* const constant = "Magic";
                        ^
In file included from file1.cpp:2:0:
file.h:3:24: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
 char* const constant = "Magic";

【问题讨论】:

  • 您是否在标题中尝试了extern const char *constant;,例如在其中一个翻译单元中尝试了const char *constant = "Magic";?在 class/struct 声明之外使用时,全局变量仍然不同。
  • @πάνταῥεῖ 我认为他的意思是 const 应该有内部链接,所以链接器不应该抱怨重复的符号。
  • @vsoftco “我认为他的意思是 const 应该有内部链接”,这显然是错误的,除非同时指定 structclass static在c++中有它的含义,与c不同。
  • @πάνταῥεῖ,我同意 vsoftco。这是我从书中文字的理解。顺便说一句,我忘了在我的 main() 中调用 file2,更新了。
  • @πάνταῥεῖ 不,我不认为这是错误的。 const 似乎默认有内部链接(不需要static),我面前没有标准,但我用const constant = 10; 尝试了OP 的程序,链接器没有抱怨重复了。这里的问题是指针不是const,正如@user2079303 回答所指出的那样

标签: c++ constants


【解决方案1】:

const char *constant 不是const。它是指向const char 的非const 指针。作为命名空间范围内的非const 变量,它默认具有外部链接,因此您会遇到多个定义错误。

const char * const constantconst 并且会按照您的预期行事。

更新:

另一方面,char* const constant 将是指向charconst 指针。作为const,它在命名空间范围内默认具有内部链接。

但是,您不应使用字符串文字对其进行初始化(正如编译器警告指出的那样),因为标准不允许这样做(这种转换在 c++11 中是非法的,并且在此之前已被弃用)。字符串文字允许存储在只读内存中,并且不允许您在运行时修改它们。这就是为什么用指向非const char 的指针指向字符串文字是危险的。

【讨论】:

  • 另外,值得注意的是,const 限定了其 left 上的任何内容,除非用作第一个限定符,因此原始定义与 char const * constant 相同- charconst,但不是指针。
  • 在 const char* const 常量中,第一个 const 告诉指针指向的 char 是常量,第二个 const 告诉指针指向的是常量地址,对吗?如果我有 char* const constant = "Magic" 是什么意思?我已经更新了我从程序中得到的行为。我会接受你的回答,但如果你能回答这个额外的问题,那真的很有帮助!
  • char* const constant = "Magic" 表示指针是 const(即,您不能将指针重新分配给另一个 C 样式字符串/字符串文字)并指向 char。此外,C++ 不赞成使用指向字符的指针来指向字符串文字,它必须是指向 const char 的指针。换句话说,char* const constant = "Magic" 产生 warning: deprecated conversion from string constant to 'char*'
  • @vsoftco,这解释了很多!请注意:当我使用 char* const constant = "Magic" 时,我的编译器会给出警告而不是错误。但我同意这不是一个好的编程习惯
  • @dannycrane 是的,确实,在我意识到之后编辑了我的评论。
猜你喜欢
  • 1970-01-01
  • 2016-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多