2013-09-24 116 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