简体   繁体   English

具有纯虚函数的模式利用多态性

[英]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:所以这是我的问题:

  1. Why is not letting me to compile the code with this modification?为什么不让我用这个修改编译代码? Suppose that I' have already implemented move in the other two structs.假设我已经在其他两个结构中实现了move
  2. What should be the correct pattern to create the desired behaviour?创建所需行为的正确模式应该是什么? (Being creating a base class with a virtual pure funct. and later using that definition to getting advantage of polymorphism. (正在创建一个具有虚拟纯函数的基础 class。然后使用该定义来利用多态性。

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_tPiece_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM