c++继承.对象调用超类方法而不是自己的方法

C++ Inheritance. Object calls super-class method instead of its own method?

本文关键字:自己的 方法 类方法 继承 对象 调用 超类 c++      更新时间:2023-10-16

我有两个类,

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方法

你应该声明一个成员函数

void print()

是虚的,即

virtual void print()

除此之外,您还应该创建一个指向Animal的指针向量

vector<Animal *>

在main中使用new创建新对象。然后它会像预期的那样工作。也就是说,你的main应该是这样的

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的建议,您可以选择使用智能指针类之一。

不能对静态类型对象进行多态性。你需要使用指针或引用。

请尝试vector<unique_ptr<Animal>>以避免内存管理问题。

你刚刚遇到了对象切片:)

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

就像其他人说的,你不能静态地声明一个动物数组,因为它只会为动物提供足够的空间,而像鸟这样的东西会被切片。

多态性只影响引用指针:

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