2012-11-20 190 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"); 
}