编辑 - 澄清我的问题的目标: 我失去了大量的时间来诊断我希望链接器报告的问题,这是由于一种公认的糟糕的编程风格造成的,例如在将一个代码块从一个编译单元复制粘贴到另一个编译单元,然后对其进行修改。
我正在寻找一种在编译/链接时检测此问题的方法。
在此设置中:
A.H
void foo();
A.cpp
struct A {
int values[100];
A(){
std::cout << __FILE__ << ": A::A()\n";
}};
void foo(){
A a;
}
的main.cpp
#include "A.h"
struct A {
double values[100];
A(){
std::cout << __FILE__ << ": A::A()\n";
}};
int main(){ foo(); }
// void foo(){} ===> this would cause a linker error
我希望链接器报告结构A
或至少构造函数A::A()
被定义两次。
然而,g ++ 4.4链接就好了。运行代码表明,在这种情况下,链接器选择使用A.cpp。{/ p>中的A
$ g++ -Wall A.cpp main.cpp && ./a.out
A.cpp:3
A.cpp:7
A.cpp:3
当两个目标文件中存在函数 foo()
时,链接器会报告多重定义,但对于结构,它不会。
编辑:刚使用nm -C *.o
找到A.o和main.o都将A::A()
定义为弱符号。这使得它可以从具有相同名称的符号池中“选择”。也许这个问题可以改为“如何让编译器生成强符号?”......
00000000 W A::A()
如何检测此问题?
答案 0 :(得分:2)
也许问题可以改为“如何让编译器生成强符号?”......
尝试限制inline
功能的使用:
struct A {
A();
};
// Inside A.cpp
A::A() {
std::cout << __FILE__ << ": A::A()\n";
}
实现更有可能报告未声明为inline
的函数的ODR违规(包括那些隐式声明为inline
的函数,就像内部定义的成员一样一个类定义),虽然严格来说,这种诊断从不需要。
答案 1 :(得分:0)
这不是问题,也不是重新定义。这就是C ++的工作原理。想一想 - 你把类定义放在标题中(暴露声明只是很少见)。标题几乎被复制粘贴到使用它们的每个翻译单元中。在多个TU中具有多个相同类的定义不能是错误。所以,这不是要解决的问题。
如果在同一名称下定义了不同的类,编译器/链接器应该会抱怨。