我有一个有趣的问题,我想知道为什么GCC / G ++没有抓住这个并抛出某种错误。
抱歉这需要多少文件,但我尽可能地减少了问题。
Interface.H
class BaseClass {
public:
virtual void hello() = 0;
};
void rememberClass(BaseClass* foo);
void callFunc();
Interface.C
#include "Interface.H"
namespace {
typedef void (BaseClass::*memfunptr)();
memfunptr func;
BaseClass* obj;
}
void rememberClass(BaseClass* foo) {
func = &BaseClass::hello;
obj = foo;
}
void callFunc() {
(obj->*func)();
}
Class1.H
class Class1 {
public:
Class1();
};
的 Class2.H
class Class2 {
public:
Class2();
};
Class1.C
#include "Interface.H"
#include "Class1.H"
#include <iostream>
class HelloClass : public BaseClass {
public:
HelloClass() {}
void hello() {
std::cout << "Calling Hello" << std::endl;
}
};
Class1::Class1() {
HelloClass* foo = new HelloClass();
rememberClass(foo);
}
Class2.C
#include "Interface.H"
#include "Class2.H"
#include <iostream>
class HelloClass : public BaseClass {
public:
HelloClass() {}
void hello() {
std::cout << "Calling Hello 2" << std::endl;
}
};
Class2::Class2() {
HelloClass* foo = new HelloClass();
rememberClass(foo);
}
MAIN.C
#include "Class2.H"
#include "Interface.H"
int main(int argc, char** argv) {
Class2 a;
callFunc();
}
输出
g++ Class1.C Interface.C main.C Class2.C
./a.out
Calling Hello
如上所示,即使我正在构建Class2
,它也会打印Class1
的输出。这是因为HelloClass
和Class1
中Class2
的vtable与HelloClass :: hello()具有相同的地址,它是Class1.C中函数的地址< / p>
我假设这是因为当GCC正在进行链接时,它会看到具有相同错位名称的类的vtable,并且只丢弃其中一个。但它应该警告这个吗?甚至会导致错误。我尝试过-Wall和-Wextra,但没有提到任何内容。
答案 0 :(得分:4)
不,标准明确允许编译器在这种情况下默默地做错事。
显然,您在同一程序中为同一个装饰名称定义了两个冲突的定义,从而导致未定义的行为。
它被称为 ODR &#34; One Definiton Rule&#34; 。
第3.2章。
答案 1 :(得分:1)
为名称空间使用显式名称