为什么C ++中的多重定义错误不是由const int声明引起的?

时间:2014-08-28 08:41:28

标签: c++ linker

我有一个标题文件foo.h

#ifndef __FOO_H__
#define __FOO_H__

const char* USB_MANAGER_DBUS_SERVICE =  "com.USBService";
#define  USB_MANAGER_DBUS_OBJ_PATH  "/com/USB/MgrObject"
const int  DBUS_CONNECTION_MAX_RETRY_TIME  = 5;

#endif

包含foo.h的许多cpp文件。

foo.c bar.c

将它们一起编译时,"多重定义错误"出现。

Linking CXX shared library:
foo.cpp.o:(.data.rel.local+0x0): multiple definition of `USB_MANAGER_DBUS_SERVICE'
bar.cpp.o:(.data.rel.local+0x0): first defined here

所以我有以下两个问题:

  1. 为什么#define导致链接错误?
  2. 为什么const int导致链接错误?

5 个答案:

答案 0 :(得分:4)

#define USB_MANAGER_DBUS_OBJ_PATH在编译单元中是常量,它是文本替换。

TU的const int常量DBUS_CONNECTION_MAX_RETRY_TIME也是如此。 const使变量只读,它基本上将其声明为可修改的左值,它有implicit internal linkagefrom这些{{ 3}}

const char* USB_MANAGER_DBUS_SERVICE =  "com.USBService";

为什么USB_MANAGER_DBUS_SERVICE会导致链接器错误?

它不是const,因为指针不是常量值,只是指向的内容。

const char* const USB_MANAGER_DBUS_SERVICE =  "com.USBService";
//          ^^^^^ added const

将是const

答案 1 :(得分:1)

定义不会导致链接错误,因为预处理器只是将字符串文字粘贴到代码的不同部分,而不是引用某些目标文件中定义的某个对象。

const int不会导致链接错误,因为const意味着内部链接,所以最终每个编译单元都有一个常量。

您可以通过在标头文件中定义extern const char* USB_MANAGER_DBUS_SERVICE;并在其中一个源文件中定义const char* USB_MANAGER_DBUS_SERVICE = "..."来修复重新定义错误。

答案 2 :(得分:1)

" #define" d令牌已经由预处理器处理,甚至在编译器发挥作用之前。

在C ++和" const int"在编译时评估值,即" const int"等同于类型安全定义(因此应优先于#define)。

编译器实际为链接器创建的唯一符号是&#34; USB_MANAGER_DBUS_SERVICE&#34;,因为只有指针指向的目标是&#34; const&#34;,而不是指针本身。< / p>

答案 3 :(得分:0)

这就是问题所在。通过#ifndef FOO_H 包装,您可以避免在.c或.cpp文件中多次包含foo.h,但是当链接器将所有不同的目标文件链接在一起时,您有多个定义。 补救措施是你在foo.h中使用如下:

#ifndef __FOO_H__
#define __FOO_H__

extern const char* USB_MANAGER_DBUS_SERVICE;
#define  USB_MANAGER_DBUS_OBJ_PATH  "/com/USB/MgrObject"
extern const int  DBUS_CONNECTION_MAX_RETRY_TIME;

#endif

并且,只有一个.c或.cpp文件(即一个源文件),请使用以下命令: const char * USB_MANAGER_DBUS_SERVICE =&#34; com.USBService&#34 ;; const int DBUS_CONNECTION_MAX_RETRY_TIME = 5;

这将解决链接器抱怨的多重定义问题。

答案 4 :(得分:0)

const char* USB_MANAGER_DBUS_SERVICE =  "com.USBService";

此指针指向的字符串是const,但指针不是const,因此它是一个多重定义。将其更改为

const char USB_MANAGER_DBUS_SERVICE[] = "com.USBService";

const int没有链接错误,因为它是一个实常数,而不是一个常量修饰符。因此,它被视为应用程序的static数据。

顺便提一下,如果你为指针放入另一个const

const char* const USB_MANAGER_DBUS_SERVICE = "com.USBService";

既然指针也是一个合适的常数,但我不确定它是否会起作用。您可以将其声明为extern,然后在一个编译单元中定义它,但最简单的是我向您展示的第一个语法。