具有相同名称的多个类导致vtable问题

时间:2014-04-14 12:25:26

标签: c++ vtable

我有一个有趣的问题,我想知道为什么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的输出。这是因为HelloClassClass1Class2的vtable与HelloClass :: hello()具有相同的地址,它是Class1.C中函数的地址< / p>

我假设这是因为当GCC正在进行链接时,它会看到具有相同错位名称的类的vtable,并且只丢弃其中一个。但它应该警告这个吗?甚至会导致错误。我尝试过-Wall和-Wextra,但没有提到任何内容。

2 个答案:

答案 0 :(得分:4)

不,标准明确允许编译器在这种情况下默默地做错事。

显然,您在同一程序中为同一个装饰名称定义了两个冲突的定义,从而导致未定义的行为

它被称为 ODR &#34; One Definiton Rule&#34;

第3.2章。

答案 1 :(得分:1)

为名称空间使用显式名称