C++继承。对象调用超类方法而不是自己的方法?

问题描述:

所以我有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; 
} 

出于某种原因,我的代码(这是不是)调用超在这两种情况下都需要使用“打印方法”

你应该声明一个成员函数

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

你不能用静态类型的对象做多态。你需要使用指针或引用。试试vector<unique_ptr<Animal>>以避免内存管理头痛。

你恰好碰到物体切片:)

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

的人说,你不能staticly声明动物的数组,因为它只会使有足够的空间来存储动物,事情就是这样鸟会得到切片。

+0

+1。是。相反,您必须声明一个对动物的引用数组(或指向动物的指针)。 –

+0

是的,我也忘了! – snotyak

多态性不仅影响引用指针

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; 
    } 
    // ... 
};