[英]Pattern with pure virtual functions getting advantage of polymorphism
Suppose the following code:假设以下代码:
struct Piece_t {
virtual ~Piece_t() = default;
std::string type;
};
struct Empty_t : Piece_t {
Empty_t() { };
bool run() { return false; };
};
struct Pawn_t : Piece_t {
Pawn_t() {
type = "Pawn";
}
bool move() {
return false;
}
};
struct Board_t {
using Cols = std::vector<Piece_t>;
using Board = std::vector<Cols>;
Board_t(size_t N = 8) : b{ Board(N, Cols(N, Empty_t())) } {
for (size_t i = 0; i < N; i++) {
b[1][i] = Pawn_t();
b[N - 2][i] = Pawn_t();
}
//more init's here...
}
Board b;
};
Here I have a Piece_t
, and Im creating a Board_t
, which has a std::vector<std::vector<Piece_t>>
.这里我有一个Piece_t
,我创建了一个Board_t
,它有一个std::vector<std::vector<Piece_t>>
。 Fair enough, however, now suppose that I want to add a pure virtual function to Piece_t
, like move
:但是,很公平,现在假设我想将纯虚拟 function 添加到Piece_t
,例如move
:
struct Piece_t {
virtual bool move() = 0;
virtual ~Piece_t() = default;
std::string type;
};
Doing this, however, is going to give me compilation errors, because I can not instantiate a std::vector<Piece_t>
like I do in Board
.但是,这样做会给我带来编译错误,因为我无法像在Board
中那样实例化std::vector<Piece_t>
。 This seems strange to me, because I'm actually doing an init with Empty_t
, and not with Piece_t
.这对我来说似乎很奇怪,因为我实际上是在使用Empty_t
进行初始化,而不是使用Piece_t
。 So here are my questions:所以这是我的问题:
move
in the other two structs.假设我已经在其他两个结构中实现了move
。Why is not letting me to compile the code with this modification?为什么不让我用这个修改编译代码?
You are experiencing object slicing .您正在体验object 切片。 std::vector<Piece_t>
stores only objects of type Piece_t
. std::vector<Piece_t>
仅存储Piece_t
类型的对象。 Imagine a contiguous array of Piece_t
classes back-to-back.想象一个连续的Piece_t
类数组。 There is no room to store anything more in between.两者之间没有空间可以存储更多东西。
Since Pawn_t
is a Piece_t
, it's sliced back down to Piece_t
and that part gets stored.由于Pawn_t
是Piece_t
,它被切回到Piece_t
并且该部分被存储。 Unfortunately an instance of Piece_t
can't exist since it's an abstract class, hence the compile error.不幸的是Piece_t
的实例不存在,因为它是一个抽象的 class,因此会出现编译错误。
What should be the correct pattern to create the desired behaviour?创建所需行为的正确模式应该是什么?
Store pointers (or references) to objects instead.而是存储指向对象的指针(或引用)。
For example, using std:vector<std::unique_ptr<Piece_t>>
.例如,使用std:vector<std::unique_ptr<Piece_t>>
。
struct Board_t {
using Row = std::vector<std::unique_ptr<Piece_t>>;
using Board = std::vector<Row>;
Board_t(size_t N = 8) : b(N) {
for (auto& row : b)
row.resize(N);
for (size_t i = 0; i < N; i++) {
b[1][i] = std::make_unique<Pawn_t>();
b[N - 2][i] = std::make_unique<Pawn_t>();
}
//more init's here...
}
Board b;
};
c++ runtime polymorphism is usually obtained instantiating the derived classes on the heap and accessing them via base class pointers/references, for example: c++ 运行时多态性通常通过在堆上实例化派生类并通过基 class 指针/引用访问它们来获得,例如:
class Piece_t {};
class Empty_t : Piece_t {};
class Pawn_t : Piece_t {};
std::vector<std::unique_ptr<Piece_t>> vec;
std::unique_ptr<Piece_t> e1 = std::make_unique<Empty_t>();
vec.push_back(std::move(e1));
vec.push_back(std::make_unique<Pawn_t>());
vec[0]->some_virtual_method();
Note that this is not the only polymorphic mechanism available in c++.请注意,这不是 c++ 中唯一可用的多态机制。 You may want to read a good c++ book while experimenting.您可能想在试验时阅读一本好的 c++ 书。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.