2013-09-24 74 views
1

我认为类型会自动解决最深的部分他们可以。如果Cat : Animal和你打电话cat->talk(),如果Cat覆盖Animaltalk(),猫会说“喵”,而不是一些奇怪的通用Animal抱怨提供基类Animal继承决议

所以我很困惑这个问题:

struct Animal 
{ 
    virtual void talkTo(Animal* o) { 
    puts("Animal-Animal") ; 
    } 
} ; 

struct Cat : public Animal 
{ 
    virtual void talkTo(Animal* o) { 
    puts("Cat-Animal") ; 
    } 
    virtual void talkTo(Cat* o) { 
    puts("Cat says meow to Cat") ; 
    } 
} ; 

下面是一些调用代码:

Cat *cat = new Cat() ; 
    cat->talkTo(cat) ; //Cat says meow to Cat 

    Animal *animalCatPtr = cat ;  
    cat->talkTo(animalCatPtr) ; //Cat-Animal 

最后一行在这里,在这里我送Catcat->talkTo,但我使用animalCatPtranimalCatPtr仍然指代Cat,但它的解析仅仅是函数调用中的Animal

如何使传递指针解析为层次结构中最深的类型,它真的是?我不想做一系列的dynamic_cast<>测试,看看我手上的Animal是否真的是CatDog或你有什么。

+2

只有'void(Animal *)'成员函数被覆盖。另一个是* new *重载,只在'Cat'中定义。 –

回答

1

所以,你必须使用“双重分派”来实现这一目标。肮脏

基本上,作为wikipedia link说,

的问题是,虽然虚拟功能在C++动态分派,函数重载静态完成。

所以,你所要做的就是修改class Cat

struct Cat : public Animal 
{ 
    virtual void talkTo(Animal* o) { 
    //puts("Cat-Animal") ; 
    o->talkTo(this) ; // TURN THE INVOKATION AROUND ("double dispatch") 
    } 
    virtual void talkTo(Cat* o) { 
    puts("Cat says meow to Cat") ; 
    } 
} ; 

现在,

cat->talkTo(animalCatPtr) ; 

animalCatPtr实际上一个Cat*。但是talkTo函数并不知道,直到我们在Cat::talkTo(Animal*)中“调用invokeation”。

如果animalCatPtr实际上只有一个Animal,那么我们将在基类Animal结束了,调用Animal::talkTo(Cat*)如果是可用的,或者如果Animal::talkTo(Animal*)仅功能可用。

如果animalCatPtr实际上是Cat,那么我们最终将调用Cat::talkTo(Cat*),这是我们想要的行为。

2

您想双重分发的形式,看到http://en.wikipedia.org/wiki/Double_dispatch

+0

换句话说,'dynamic_cast <>()' – bobobobo

+1

@bobobobo - 根本不用动态调度,您可以使用传递给动态对象的基指针来多态桥接到另一个成员函数。 –

+0

好吧,我明白了。我[在下面的答案中添加了更多信息](http://stackoverflow.com/a/18987136/111307) – bobobobo