2014-04-14 48 views
0

我有一個有趣的問題,爬起來,我想知道爲什麼GCC/G ++沒有抓住這個並拋出某種錯誤。同一個名稱導致vtable問題的多個類

道歉這有多少文件,但我儘可能減少了這個問題。

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(); 
}; 

Ç lass2.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輸出。這是因爲在兩個Class1Class2虛函數表的HelloClass有)相同的地址HelloClass ::你好(和它的功能是在Class1.C

我假定這是地址

,因爲當海灣合作委員會正在做鏈接,它看到vtables的類與相同的mangled名稱,只是丟棄其中之一。但是它應該警告這個嗎?甚至導致錯誤。我曾嘗試使用-Wall和-Wextra,但沒有提及。

+0

使用命名空間? – Prabhu

+0

謝謝,我明白如何解決它,只是想知道爲什麼它不抱怨 – Salgar

回答

4

不,標準明確允許編譯器在這種情況下默默地做錯誤的事情。

明確地說,您正在導致未定義的行爲,因爲在同一程序中對同一裝飾名稱有兩個衝突的定義。

它被稱爲ODR「一個定義規則」

第3.2章。

+0

你有任何章節/詩歌嗎? – Salgar

+0

謝謝,只是有一個閱讀,似乎只有某些事情被檢查,以確保他們是同一類,否則如你所說,未定義的行爲派對。 – Salgar

1

對命名空間使用顯式名稱

相關問題