2011-11-22 97 views
0

所以我有2班,C++繼承。對象調用超類方法而不是自己的方法?

class Animal{ 
public: 
    Animal(int age, int hairCount) { 
     howOld = age; 
     numOfHairs = hairCount; 
    } 

    void print(){ 
     cout << "Age: " << howOld << "\tNumber of Hairs: " << numOfHairs << endl; 
    } 

protected: 
    int howOld; 
    int numOfHairs; 
}; 



class Bird: public Animal{ 
public: 
    Bird(int age, int hairCount, bool fly) : Animal(age, hairCount) { 
     canItFly = fly; 
    } 

    void print() { 
     cout << "Age: " << howOld << "\tNumber of Hairs: " 
      << numOfHairs << "\tAbility to fly: " << canItFly << endl; 
    } 
protected: 
    bool canItFly; 
}; 

如果在主程序中,我有這樣的事情:

#include <vector> 
#include <iostream> 
using namespace std; 

int main() { 
    vector<Animal> list; 
    list.pushBack(Bird(5,10000,true)); 
    list.pushBack(Animal(14,1234567)); 

    for(int i = 0; i < list.size(); i++){ 
     list[i].print(); //Calls the super class for both outputs 
    } 
    return 0; 
} 

出於某種原因,我的代碼(這是不是)調用超在這兩種情況下都需要使用「打印方法」

回答

4

你應該聲明一個成員函數

void print() 

是虛擬的,即

virtual void print() 

Additionaly來,你應該建立一個指針的向量,以動物

vector<Animal *> 

在主創建使用新的新對象。然後它會按預期工作。這就是說你的主要應該是這樣的

vector<Animal *> list; 
Animal *bird = new Bird(5,10000,true); 
Animal *animal = new Animal(14,1234567); 
list.push_back(bird); 
list.push_back(animal); 

而且不要忘記刪除鳥類和動物,如果你不需要他們了由

delete bird; 
delete animal; 

您也可以選擇使用智能指針類之一,由本傑明林德利建議。

+0

編輯:我遺漏了那個小細節。我確實對超類有虛擬的。不知道爲什麼它不打印。 – snotyak

+0

哎呀,我已經糾正了我的答案。 – Beginner

+0

在聲明向量之後,我無法使用list [i] .print()調用print方法。 – snotyak

4

你不能用靜態類型的對象做多態。你需要使用指針或引用。試試vector<unique_ptr<Animal>>以避免內存管理頭痛。

4

你恰好碰到物體切片:)

http://en.wikipedia.org/wiki/Object_slicing

的人說,你不能staticly聲明動物的數組,因爲它只會使有足夠的空間來存儲動物,事情就是這樣鳥會得到切片。

+0

+1。是。相反,您必須聲明一個對動物的引用數組(或指向動物的指針)。 –

+0

是的,我也忘了! – snotyak

3

多態性不僅影響引用指針

Bird bibo; 
Crocodile claus; 

Animal & a1 = bibo, & a2 = claus; 

a1.print(); 
a2.print(); 

只具有普通的Animal a不給你訪問任意多態行爲,而事實上它可能甚至沒有任何意義:由於每個動物都是某種類型的具體動物,因此你的基類應該是抽象的。

集裝箱怎麼樣?由於從基類派生的具體類可以具有可變大小,因此您無法直接將它們放入容器中。相反,您應該將指針指向基類到容器中。

選擇的指針是std::unique_ptr<Animal>,它是輕量級和最簡單的生命週期管理形式。它的工作原理是這樣的:

#include <memory> 
#include <vector> 

typedef unique_ptr<Animal> AnimalPtr; 
typedef std::vector<AnimalPtr> Zoo; 

Zoo z; 

z.push_back(AnimalPtr(new Bird)); // old-style 
z.emplace_back(new Crocodile);  // new-style, better 

最後,就如何使Animal抽象一點不起眼的細節。我們可以聲明print()是純虛擬的。但是我們也想要一個基本的實現。我們可以這樣做:

struct Animal 
{ 
    virtual void print() const = 0; 
    // ... 
}; 
void Animal::print() const 
{ 
    out << "Age: " << howOld << "\tNumber of Hairs: " << numOfHairs << endl; 
} 

struct Bird 
{ 
    virtual void print() const 
    { 
    Animal::print(); // call base function first 
    cout << "Ability to fly: " << canItFly << endl; 
    } 
    // ... 
}; 
相關問題