2012-11-20 90 views
1

所以我得到一些奇怪的行爲與某些類層次結構我想我make.I實現圖形和我通過使被將AdjacencyMatrixGraph和AdjacencyListGraph這樣實現的Graph類做古怪的行爲它們可以被任何想要使用它們的圖表用作圖表。與繼承和C++

我在Graph中有一個純的虛函數,它被AdjacencyMatrixGraph中的函數覆蓋,但是我有一個非虛函數名稱相同,但在Graph中具有不同的簽名。在訪問AdjacencyMatrix類時,我無法調用Graph類的非虛擬方法,但是當我重命名非虛擬方法時,它工作正常。

像這樣:

當類看起來像這樣

class Graph 
{ 
public: 
    virtual void addVertex(Vertex vert, bool bidirectional)=0; 
    void addVertex(unsigned int from, unsigned int to, double weight, bool bidirectional) 
} 

class AdjacencyMatrixGraph : public Graph 
{ 
... 
} 




AdjacencyMatrixGraph test; 
Vertex vert; 
test.addVertex(vert,false); //this statement compiles and works fine 
test.addVertex(0,0,10.f,false) //this statement fails to compile and says cadidates are addVertex(Vertex, bool) 

但是,如果我重新命名,像這樣

class Graph 
{ 
public: 
    virtual void addVertex(Vertex vert, bool bidirectional)=0; 
    void addVert(unsigned int from, unsigned int to, double weight, bool bidirectional) 
} 

AdjacencyMatrixGraph test; 
Vertex vert; 
test.addVertex(vert,false); //this statement compiles and works fine 
test.addVert(0,0,10.f,false) //this statement compiles and works fine 

非虛方法這是沒有意義的我,因爲我認爲編譯器看見addVertex(頂點,布爾)和addVertex(無符號整數,無符號整型,雙,布爾)爲兩個完全不同的符號。所以不應該被繼承覆蓋,即使它不應該是可能的,因爲符號有不同的論點。

回答

4

派生類中的定義隱藏基類過載聲明。

爲了使那些到派生類的範圍內,使用using聲明,像

using Graph::addVertex; 
在派生類

順便說一句,這是一個FAQ。詢問前查看常見問題解答通常是一個好主意。甚至只是一般。 :-)

+0

這是非常有用的謝謝,但爲什麼?雖然我可以繼續我的工作,但知道爲什麼會發生這種情況,不僅僅是知道我發生的事情,而是幫助我更多。 –

+0

@TheDude:對「爲什麼」沒有真正的好答案,這只是一個艱難的語言設計決定。與當前的規則,由派生定義隱藏基類過載,工作方式相同通過在內部範圍限定具有相同名稱的變量隱藏外部範圍變量(比方說)。所以,現行規則強調*統一規則*。也,目前的規則防止在基類的加成過載M的,從(默認)影響重載解析在派生類的與M的代碼,以便在當前規則還強調*預見性*。其他選擇可能已經完成。 –

1

在這種情況下AdjacencyMatrixGraph隱藏Graph::addVertex(unsigned int from, unsigned int to, double weight, bool bidirectional)。要將該功能納入範圍,請使用using聲明,如下所示:

class A 
{ 
public: 
virtual void foo(int) = 0; 
virtual void foo(std::string) { std::cout << "foo(string)" << std::endl; } 
}; 

class B : public A 
{ 
public: 
using A::foo; //this unhides A::foo(std::string) 
virtual void foo(int) { std::cout << "foo(int)" << std::endl; } 
}; 

int main() 
{ 
B b; 
b.foo(1); 
b.foo("hello"); 
}