2015-09-07 56 views
-3

我有一個基類Animal和模板派生類Specie<T>。當我有一個指向基類Animal的指針時,我想使用多態克隆來返回右派生類型的對象。我實現的克隆似乎總是返回一個指向Animal的指針。不是我所期望的,但我不明白爲什麼。另一方面,如果我手動執行dynamic_cast,它就會起作用。任何想法 ?C++意外的多態克隆行爲

#include <iostream> 


class Dog; 
class Cat; 
class Rat; 


// Base class 
class Animal{ 

public: 
    virtual Animal * clone() = 0; 

}; 





// Derived class 
template <class T1> 
class Specie: public Animal{ 


public: 

    Specie<T1> * clone(); 

    void DoSomething(); 


}; 



// Purpose of clone(): Return a pointer of type Specie<T1> when applied 
// to a pointer to class Animal 
template <class T1> 
Specie<T1> * Specie<T1>::clone(){ 

    Specie<T1> *obj; 

    obj = dynamic_cast<Specie<T1> *>(this); 

    return obj; 

} 






// To identify a Dog 
template <> 
void Specie<Dog>::DoSomething(){ 

    std::cout << "This is a Dog..." << std::endl; 

} 


// To identify a Cat 
template <> 
void Specie<Cat>::DoSomething(){ 

    std::cout << "This is a Cat..." << std::endl; 

} 


int main(){ 

Specie<Dog> Dingo; 
Specie<Cat> Tom; 

Dingo.DoSomething(); 
Tom.DoSomething(); 


Animal *animal3; 
animal3 = &Dingo; 






// The following works 
// Successfull conversion from pointer-to-Animal to pointer-to-Specie<Cat> with dynamic_cast without using clone() 
Animal *animal4 = new Specie<Cat>; 
Specie<Cat> *animal5; 

// Here I can convert the pointer to Animal to a pointer to Specie<T> 
// using dynamic_cast. If animal5 was not of the correct type, the compiler would return an error. 
animal5 = dynamic_cast<Specie<Cat>*>(animal4); 
animal5->DoSomething(); // result ok 



// I want to do the same in an automated manner with clone() 
// The following DOES NOT WORK with clone() 
// clone() does not return a pointer to Specie<T> as expected 
// but a pointer to Animal. The compiler complains. 
Animal *animal6 = new Specie<Dog>; 
Specie<Dog> *bobby; 
bobby = animal6->clone(); 


return 0; 
} 

錯誤:「*動物」不能被分配給類型的實體「正金*」 巴比= animal6->克隆()類型的值;

它爲什麼在main中使用dynamic_cast但不使用clone()? 在此先感謝。

+0

順便說一下,你的'Clone'只是返回'this'而不是'* this'的副本。 – Jarod42

回答

1

它不無dynamic_cast工作,因爲Animal::clone靜態返回類型爲Animal*動態類型animal6Specie<Dog>,但是它沒有輸入在編譯時推導出的函數返回clone函數的類型。

如果你真的需要這個,dynamic_cast是必要的,但這是一種代碼味道。如果你發現自己需要絕對動態類型的對象,而不僅僅是使用虛擬功能,那麼你應該考慮重新設計。

+0

謝謝。我在函數clone()中使用dynamic_cast,但它似乎沒有幫助。 –

+0

@ ChristopheJ.Ortiz不會改變'clone'函數的靜態類型。 – TartanLlama