2009-09-27 77 views
7

我在C++中面臨的一個問題:C++重寫/過載問題

#include <iostream> 

class A 
{ 
protected: 
    void some_func(const unsigned int& param1) 
    { 
    std::cout << "A::some_func(" << param1 << ")" << std::endl; 
    } 
public: 
    virtual ~A() {} 
    virtual void some_func(const unsigned int& param1, const char*) 
    { 
    some_func(param1); 
    } 
}; 

class B : public A 
{ 
public: 
    virtual ~B() {} 
    virtual void some_func(const unsigned int& param1, const char*) 
    { 
    some_func(param1); 
    } 
}; 

int main(int, char**) 
{ 
    A* t = new B(); 
    t->some_func(21, "some char*"); 
    return 0; 
} 

我用G ++ 4.0.1編譯錯誤:

$ g++ -W -Wall -Werror test.cc 
test.cc: In member function ‘virtual void B::some_func(const unsigned int&, const char*)’: 
test.cc:24: error: no matching function for call to ‘B::some_func(const unsigned int&)’ 
test.cc:22: note: candidates are: virtual void B::some_func(const unsigned int&, const char*) 

爲什麼我必須指定類B中some_func(param1)的調用是A :: some_func(param1)?它是一個g ++ bug還是來自g ++的隨機消息,以防止我看不到的特殊情況?

+0

這很奇怪。受保護的基類函數應該對子類可見,虛擬,重載或不可重載。 – 2009-09-27 22:30:23

回答

11

問題是,在派生類中,您將隱藏受保護的方法在基類中。你可以做幾件事,要麼你完全限定派生對象中的受保護方法,要麼使用using指令將該方法帶入範圍:

class B : public A 
{ 
protected: 
    using A::some_func; // bring A::some_func overloads into B 
public: 
    virtual ~B() {} 
    virtual void some_func(const unsigned int& param1, const char*) 
    { 
    A::some_func(param1); // or fully qualify the call 
    } 
}; 
+0

我爲什麼隱藏它?我只是重寫第二個。通常情況下,g ++必須在B的vtable中保留重載init的簽名,但事實並非如此。 爲什麼不保留每種方法的簽名?爲什麼它失去了超載(我只是重新定義其中之一)? – fedj 2009-09-27 22:40:06

+1

當您在派生類中定義具有名稱的方法時,它將隱藏層次結構中以上具有相同名稱的所有其他方法。當編譯器通過引用靜態類型B發現你正在調用'some_func'時,它會嘗試將它與B中的所有'some_func'匹配,並且不會嘗試提升層次結構以在基類中查找可能的匹配。 – 2009-09-27 22:42:42

+0

它是避免大vtable大小的默認g ++行爲還是C++定義,並且每個編譯器都會出現相同的錯誤? 因爲通常情況下,如果它不是A類中的重載(也就是說另一個方法名稱),則簽名將被複制到B類vtable中。 – fedj 2009-09-27 22:48:23