c++ - 如何在 C++ 中声明抽象类的向量列表?
问题描述
我有几个类继承自一个主类。为了简单起见,我过度简化了类定义以使其简短直接。
动物.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"; }
};
检测.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>
包含每个继承类的多个实例的 a。
主文件
#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;
}
}
我期望以下输出:
我是一只鸟
我是一只鸟
我是昆虫
我是昆虫
但我得到了:
我是动物
我是动物
我是动物
我是动物
我知道这与“矢量生物”这一行有关;. It is calling the constructor for
动物. But my intention is to tell the compiler, that this
生物points to an array of
动物inherited classes, might be
鸟might be
昆虫, the point is: they all implement their own unique respective version of
toString()`。
我可以做些什么来声明从同一个祖先继承的对象的多态数组?
解决方案
您不能使用值语义(阅读有关对象切片的信息)。您必须使用指针。
例子:
#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;
}
}
推荐阅读
- jsf - Wildflt 13 WELD-001304:范围类型 javax.enterprise.context.SessionScoped 的多个上下文处于活动状态
- python - 如何从 django 中删除记录?
- php - Laravel 6 错误 Action Facade\Ignition\Http\Controllers\ShareReportController not defined 是什么意思?
- php - 如何在表格中显示二叉树数据
- powershell - 更改多个文件的特定行的值
- python - 如何为以下数据创建适当的数据透视表或聚合表?
- python - 即使添加了应用程序名称空间,Django reverse() 方法仍然抛出 NoReverseMatch 异常错误
- html - 无法识别 CSS 或控制背景颜色的元素
- javascript - 当确切的日光切换发生时,新的 Date() 无法按预期工作
- r - 配方因 caret::train 而失败