所以我有2个班,
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;
}
出于某种原因,我的代码(不是这样)在两种情况下调用超类的print方法。
答案 0 :(得分:4)
您应该声明一个成员函数
void print()
是虚拟的,即
virtual void print()
除此之外,你应该创建一个指向Animal
的指针向量vector<Animal *>
在main中使用new创建新对象。然后它将按预期工作。那说你的主要应该是这样的
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;
根据Benjamin Lindley的建议,您可以选择使用其中一种智能指针类。
答案 1 :(得分:4)
您不能对静态类型的对象进行多态操作。您需要使用指针或引用。尝试vector<unique_ptr<Animal>>
以避免内存管理问题。
答案 2 :(得分:4)
你刚遇到对象切片:)
http://en.wikipedia.org/wiki/Object_slicing
正如其他人所说,你不能静态地宣布一个动物阵列,因为它只会留出足够的空间来存放动物,像鸟类这样的东西会被切成碎片。
答案 3 :(得分: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;
}
// ...
};