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;
您也可以选择使用智能指针类之一,由本杰明林德利建议。
你不能用静态类型的对象做多态。你需要使用指针或引用。试试vector<unique_ptr<Animal>>
以避免内存管理头痛。
你恰好碰到物体切片:)
http://en.wikipedia.org/wiki/Object_slicing
的人说,你不能staticly声明动物的数组,因为它只会使有足够的空间来存储动物,事情就是这样鸟会得到切片。
+1。是。相反,您必须声明一个对动物的引用数组(或指向动物的指针)。 –
是的,我也忘了! – 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;
}
// ...
};
编辑:我遗漏了那个小细节。我确实对超类有虚拟的。不知道为什么它不打印。 – snotyak
哎呀,我已经纠正了我的答案。 – Beginner
在声明向量之后,我无法使用list [i] .print()调用print方法。 – snotyak