将派生类传递给基函数

Passing derived class to base function

本文关键字:基函数 派生      更新时间:2023-10-16

我在传递一个派生类给一个接受基类作为参数的函数时遇到了麻烦。基类由"障碍物"组成,这些障碍物将被放置在"板"上。障碍);

但是,这会导致编译器给出"no known conversion for argument…"错误。阅读周围的网站,我发现我应该传递的派生对象作为一个const,然而这会导致问题,因为const不能分配给板(因为它保存指针非const障碍)。
反过来,将Board更改为hold const障碍会在项目的其他地方引起许多问题,特别是与运营商<<冲浪板和障碍。
我曾尝试将对象作为const传递,然后使用Obstacle ob = new Obstacle ( const Obstacle ),但这使它们成为通用障碍对象,而不是玩家/桶/墙对象。

是否有办法将这些对象作为非const对象传递或将其赋值为非const对象?我尝试使用const_cast(),但这会导致未定义的行为。

函数调用的一个例子:

Board_->setvalue(x, y, Player(data, moveable, x, y));
下面是我的代码:

基类

class Obstacle
{
    public:
    Obstacle* _properlyinitialized;
    string Name;
    bool Moveable;
    int x;
    int y;
    Obstacle();
    Obstacle(string Name, bool Moveable, int x, int y);
    virtual ~Obstacle();
    bool properlyInitialized();
    friend std::ostream& operator<<(std::ostream& stream, Obstacle& Obstacle);
};

一个派生类的例子(其他派生类还没有特殊的函数)

class Player: public Obstacle
{
public:
    Player():Obstacle(){};
    Player(string Name, bool Moveable, int x, int y):Obstacle(Name, Moveable, x, y){this->_properlyinitialized = this;};
    ~Player(){};
    /*void Moveleft();
    void Moveright();
    void Moveup();
    void Movedown();*/
};

Board类头文件

class Board
{
private:
    Board* _properlyinitialized;
    int length;
    int width;
    Obstacle * * * playfield;
public:
    /*
     **ENSURE(this->properlyInitialized(),
                "Object wasn't initialized when calling object");
     */
    Board();
    Board(int length, int width);
    ~Board();
    bool properlyInitialized();
    /*
     **REQUIRE(this->properlyInitialized(),
            "Object wasn't initialized when calling properlyinitialized");
     */
    void clear();
    const int getLength();
    const int getWidth();
    Obstacle*** getBoard();
    Obstacle* getTile(int length, int width);
    void setvalue(int length, int width, Obstacle& obstacle);
    friend std::ostream& operator<<(std::ostream& stream, Board& Board);
};
std::ostream& operator<<(std::ostream& stream, Board& Board);

最后是setvalue函数

void Board::setvalue(int length, int width, Obstacle& obstacle)
{
    this->playfield[length][width] = &obstacle;//value;
    return;
}

如果需要,我很乐意提供更多的代码

不进行完整的代码检查(这不是SO的目的),让我们直接进入您提到的例程

void Board::setvalue(int length, int width, Obstacle& obstacle)
{
    this->playfield[length][width] = &obstacle;
    return;
}

设置一个三重指针

Obstacle *** playfield;

这个设计有几个不好的原因,但这里是主要的原因:当你想通过Board::playfield调用它时,它根本不清楚障碍是否仍然存在。没有人能保证玩家不会被长期摧毁,你将很难记录这一事实。

相反,我建议你让董事会拥有障碍。因此,不使用障碍物原始指针,而是设置一个唯一指针的向量

std::vector<std::unique<Obstacle> > playfield;

,然后复制或移动类:

template<typename O>
void Board::setvalue(int length, int width, O&& obstacle)
{
    playfield.push_back(std::make_unique<O>(std::forward<O>(obstacle));
}

(我把场几何放在一边,我怀疑将它与障碍物的实际存储混合在一起是否有用——但如果你仍然想要,你可以使用向量的向量或带有二维索引方案的单个向量)。

回到你的意图:使用上面的方法,你直接摆脱了所有的常数问题。你也可以。Board拥有这些东西,可以用它们做你想做的事。

这里的问题是,你试图传递一个const值(Player(data, moveable, x, y))作为参考。你不能那样做。关于您将对象存储在数组字段中的事实,您应该明确使用指针或更好的shared_ptr并将其存储在std::liststd::vector中,以避免删除问题。