2014-11-15 47 views
1

所以目前我有3个类。 ShapeSquareTriangleTriangleSquare继承自Shape。在Shape我有虚拟方法:如何用虚拟方法重载和继承优先

virtual bool myMethod(); 

virtual bool myMethod(Shape& sha); 

,并在例如Triangle我:

virtual bool myMethod(Square& sqa); 

virtual bool myMethod(Shape& tri); 

现在,在我的主要方法,我有:

Shape* m[3]; 
m[0] = new Square; 
m[1] = new Triangle; 
m[2] = new Square; 
cout << m[0]->myMethod(*m[1]); 
cout << m[0]->myMethod(*m[2]); 

当我在第一个cout中调用它时,它可以正常工作并转到(Shape& tri)的方法,但第二个方法也转到(Shape& tri)方法。我明白为什么会发生这种情况,但有什么办法可以使它成为(Square& squ)而不是Shape

谢谢

+0

听起来像访客模式的应用 – erenon

回答

3

C++选择使用重载解析来调用的方法。重载解析完全基于参数的静态类型。如果被调用的过载是一个virtual函数,则它可能会在派生类中被覆盖,在这种情况下,调用将在运行时分派到覆盖。

据我所知,您希望系统根据对象和参数类型进行多次调度。 C++不直接支持多派遣,但有一些方法来模拟它。要处理您想要的调度,可以安排您的调用以在运行时找到适当的覆盖。一种方法是将功能分成多个版本。

struct Square; 
struct Triangle' 
struct Circle; 

struct Shape { 
    virtual ~Shape() {} 

    virtual bool doMethod(Square& s) { return doMethod(static_cast<Shape&>(s)); } 
    virtual bool doMethod(Triangle& s) { return doMethod(static_cast<Shape&>(s)); } 
    virtual bool doMethod{Circle& s) { return doMethod(static_cast<Shape&>(s)); } 

    virtual bool doMethod(Shape&) = 0; 
    virtual bool myMethod(Shape&) = 0; 
}; 

struct Triangle: Shape { 
    bool myMethod(Shape& other) { return other.doMethod(*this); } 
    bool doMethod(Shape& other) { /* general case */ } 
    bool doMethod(Square& other) { /* special case */ } 
}; 
+0

谢谢你的解释,这是有道理的。然而,由于你给出的代码在实现时遇到了一些麻烦,因为Shape实际上并不知道正方形/三角形,因为它们是从Shape继承的,所以我无法创建这些虚拟方法。 – Niamh

+0

@Niamh:如果你不能转发声明需要特殊处理的形状,你需要一些处理[multiple dispatch](http://en.wikipedia.org/wiki/Multiple_dispatch)的其他方法:哪一个是最适合你的需求取决于你真正想做什么。没有“好”的解决方案:都有缺点:所发布的要求需要知道类型(即它是封闭的),但效率很高;其他方法交换更高的效率灵活性。 –

+0

感谢您提供的信息,我已经查看了其他一些方法,并在多个调度wiki页面上显示if(Circle * cir = dynamic_cast (&aShape))。 – Niamh

2

您正在寻找C++语言中不存在的功能。在C++中,动态调度发生在,只有来自调用者,而不是任何参数。

所以,当你调用myMethod(*m[2]),​​是Shape所以它会调用bool myMethod(Shape&),因为这就是超载分辨率喜欢。现在

,如果你真的想要的东西在Triangle/Square情况特殊,你可能想看看双调度:

virtual bool Triangle::myMethod(Shape& shape) { 
    return shape.myMethodImpl(*this); 
} 

这样的话,你可以有:

virtual bool Square::myMethodImpl(Triangle& triangle) { 
    // ... 
} 

其中仅可以通过第二次调度进行调用。

+0

啊,谢谢。我会阅读双重调度和如何实施它。 – Niamh