c++ - 如何在 C++ 中声明抽象类的 vector 列表?

标签 c++ inheritance vector polymorphism

我有几个类继承自一个主类。为了简单起见,我过度简化了类定义以使其简短明了。

动物.h

所有其他类继承自的主类:

class Animal {
protected:
    string name;
public:
    Animal(string name);
    virtual string toString() { return "I am an animal"; }
};

鸟.h

class Bird: public Animal {
private:
    bool canFly;
public:
    Bird(string name, bool canFly = true) 
     : Animal(name)   // call the super class constructor with its parameter
    {
        this->canFly = canFly;
    }
    string toString() { return "I am a bird"; }
};

indect.h

class Insect: public Animal {
private:
    int numberOfLegs;
public:
    Insect(string name, int numberOfLegs) : Animal(name) {
        this->numberOfLegs = numberOfLegs;
    }
    string toString() { return "I am an insect."; }
};

现在,我需要声明一个 vector<Animal>它将包含每个继承类的多个实例。

main.cpp

#include <iostream>
#include "animal.h"
#include "bird.h"
#include "insect.h"

// assume that I handled the issue of preventing including a file more than once
// using #ifndef #define and #endif in each header file.

int main() {

    vector<Animal> creatures;

    creatures.push_back(Bird("duck", true));
    creatures.push_back(Bird("penguin", false));
    creatures.push_back(Insect("spider", 8));
    creatures.push_back(Insect("centipede",44));

    // now iterate through the creatures and call their toString()

    for(int i=0; i<creatures.size(); i++) {
        cout << creatures[i].toString() << endl;
    }
}

我希望得到以下输出:

I am a bird

I am a bird

I am an insect

I am an insect

但我得到了:

I am an animal

I am an animal

I am an animal

I am an animal

我知道这与“vector 生物”这一行有关。 . It is calling the constructor for 动物 . But my intention is to tell the compiler, that this 生物 points to an array of动物 inherited classes, might bemight be昆虫, the point is: they all implement their own unique respective version of toString()`。

如何声明从同一祖先继承的对象的多态数组?

最佳答案

你不能使用 value 语义(阅读 object slicing )。您必须使用指针。

例子:

#include <iostream>
#include <memory>
#include <string>
#include <vector>

class Animal
{
 protected:
  std::string name;

 public:
  Animal(std::string name) : name(name)
  {
  }
  virtual std::string toString()
  {
    return "I am an animal";
  }
  virtual ~Animal()
  {
  }
};

class Bird : public Animal
{
 private:
  bool canFly;

 public:
  Bird(std::string name, bool canFly = true) : Animal(name)  // call the super class constructor with its parameter
  {
    this->canFly = canFly;
  }
  std::string toString()
  {
    return "I am a bird";
  }
};

class Insect : public Animal
{
 private:
  int numberOfLegs;

 public:
  Insect(std::string name, int numberOfLegs) : Animal(name)
  {
    this->numberOfLegs = numberOfLegs;
  }
  std::string toString()
  {
    return "I am an insect.";
  }
};

int main()
{
  std::vector<std::unique_ptr<Animal>> creatures;

  creatures.emplace_back(new Bird("duck", true));
  creatures.emplace_back(new Bird("penguin", false));
  creatures.emplace_back(new Insect("spider", 8));
  creatures.emplace_back(new Insect("centipede", 44));

  // now iterate through the creatures and call their toString()

  for (int i = 0; i < creatures.size(); i++)
  {
    std::cout << creatures[i]->toString() << std::endl;
  }
}

打印:

I am a bird
I am a bird
I am an insect.
I am an insect.

我也推荐阅读 Sean parent Run Time Polymorphism .思路如下:

#include <iostream>
#include <memory>
#include <string>
#include <vector>

class Animal
{
 public:
  struct Interface
  {
    virtual std::string toString() const = 0;
    virtual ~Interface()                 = default;
  };
  std::shared_ptr<const Interface> _p;

 public:
  Animal(Interface* p) : _p(p)
  {
  }
  std::string toString() const
  {
    return _p->toString();
  }
};

class Bird : public Animal::Interface
{
 private:
  std::string _name;
  bool        _canFly;

 public:
  Bird(std::string name, bool canFly = true) : _name(name), _canFly(canFly)
  {
  }
  std::string toString() const override
  {
    return "I am a bird";
  }
};

class Insect : public Animal::Interface
{
 private:
  std::string _name;
  int         _numberOfLegs;

 public:
  Insect(std::string name, int numberOfLegs)
      : _name(name), _numberOfLegs(numberOfLegs)
  {
  }
  std::string toString() const override
  {
    return "I am an insect.";
  }
};

int main()
{
  std::vector<Animal> creatures;

  creatures.emplace_back(new Bird("duck", true));
  creatures.emplace_back(new Bird("penguin", false));
  creatures.emplace_back(new Insect("spider", 8));
  creatures.emplace_back(new Insect("centipede", 44));

  // now iterate through the creatures and call their toString()

  for (int i = 0; i < creatures.size(); i++)
  {
    std::cout << creatures[i].toString() << std::endl;
  }
}

关于c++ - 如何在 C++ 中声明抽象类的 vector 列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59015672/

相关文章:

c++ - 基类的未定义模板参数

c++ - 谁能解释常量或 const 变量存储在哪里?

c++ - 分支预测优化

c# - 从 DLL 在 C# 中调用 C++ 函数 - 奇怪的参数

c++ - 使用线程对 vector 进行排序

python - 在python中将两个不同长度的数组相乘

c++ - 调用存储在 vector 中的对象的成员函数

c++ - 使用 QGraphicsView 子类用 QPainter 画一条线

.net - 为什么不继承构造函数?

c# - 是否可以提取具有主类属性的对象?