我有一个标题文件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
所以我有以下两个问题:
#define
导致链接错误?const int
导致链接错误?答案 0 :(得分:4)
#define
USB_MANAGER_DBUS_OBJ_PATH
在编译单元中是常量,它是文本替换。
TU的const int
常量DBUS_CONNECTION_MAX_RETRY_TIME
也是如此。 const
使变量只读,它基本上不将其声明为可修改的左值,它有implicit internal linkage,from这些{{ 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
,然后在一个编译单元中定义它,但最简单的是我向您展示的第一个语法。