为什么C++中的多定义错误不是由const int声明引起的
Why multiple definition error in C++ not caused by const int declaration?
我有一个头文件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
不会导致链接错误
USB_MANAGER_DBUS_OBJ_PATH
的#define
在各个编译单元中是常量,它是一个文本替换。
TU中DBUS_CONNECTION_MAX_RETRY_TIME
常量的const int
也是如此。const
使变量只读,本质上是而不是将其声明为可修改的左值,它有一个隐含的内部链接,来自这些帖子。
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
。
Define不会导致链接错误,因为预处理器只是将字符串文本粘贴到代码的不同部分,而不是引用某个对象文件中定义的某个对象。
const int
不会导致链接错误,因为const
意味着内部链接,所以最终每个编译单元都有一个常量。
您可以通过在头文件中定义extern const char* USB_MANAGER_DBUS_SERVICE;
并在某个源文件中定义const char* USB_MANAGER_DBUS_SERVICE = "..."
来修复重新定义错误。
"#define"d令牌已经由预处理器处理,甚至在编译器开始运行之前。
在C++中,"const int"值是在编译时计算的,即"const int"等效于类型安全定义(因此应该优先于#define)。
编译器实际为链接器创建的唯一符号是"USB_MANAGER_DBUS_SERVICE",因为只有指针指向的目标是"const",而不是指针本身。
问题出在这里。通过使用#ifndefFOO_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="com.USBService";const int DBUS_CONNECTION_MAX_RETRY_TIME=5;
这将解决链接器抱怨的多重定义问题。
const char* USB_MANAGER_DBUS_SERVICE = "com.USBService";
该指针指向的字符串是const,但指针不是const,因此它是一个多重定义。将其更改为
const char USB_MANAGER_DBUS_SERVICE[] = "com.USBService";
const int没有链接错误,因为它是一个实常量,而不是const修饰符。因此,它被认为是应用程序的static
数据。
顺便说一句,如果你为指针输入另一个常量
const char* const USB_MANAGER_DBUS_SERVICE = "com.USBService";
现在这个指针也是一个适当的常数,但我不确定它是否有效。您可以将它声明为extern
,然后在一个编译单元中定义它,但最简单的是我向您展示的第一个语法。
- 'max'匹配'std::function<const int &(const int &, const int &)>'无过载
- 在函数中使用 const int size 参数创建数组会在 Visual Studio 中抛出错误 C++:表达式的计
- 在类 (C++) 之外设置 const int 成员变量
- C++ 无法从 const int* 转换为 const_iterator
- 在C++中,如果"int a = 3; int* p = &a;",那么为什么不允许"const int* &pp = p",但允许"const int* const &pp = p"?
- C++如何将 std::vector 转换为 const<int> std::vector<const int>?
- 如何在字符串向量中指向const int
- 如何在 std::map<const int、int> C++ 中重载插入运算符>>?
- 为什么允许 int 和 const int 使用不同的转换函数?
- 如何通过头文件中的函数初始化 const int 数组?
- 为什么 const int 适用于字符大括号初始化?
- 不同类型的"decltype((const int)a)"和"decltype((cons
- 为什么我不能使用与"常量字符*"相同的"const int*"创建一个 int 数组?
- Const Int 宣布与 stoi 不被视为 const
- 传递 const int* 和 int* 时调用重载函数的不同版本(const int* const&/&&)
- 杀死幻数:"const int" vs "constexpr int"(或者最后没有区别)
- 作为返回类型"const int&"做什么?
- 将const int std ::数组的n元素复制到int矢量中.怎么做
- 尝试使用 const int std::array 时出错
- 构造函数中没有从 'const int [5][4]' 到 'const int **' 的已知转换