将派生类传递给基本函数 [英] Passing derived class to base function

查看:49
本文介绍了将派生类传递给基本函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法将派生类传递给接受基类作为参数的函数.基类由障碍物"组成,这些障碍物将放置在木板"空隙Board :: setvalue(int length,int width,Obstacle&障碍物;

但是,这会导致编译器给出参数的未知转换..."错误.在站点周围仔细阅读后发现,我应该将派生对象作为const传递,但是这会引起问题,因为无法将const分配给开发板(因为它持有指向非const障碍的指针).
继而,改变委员会以持有常量障碍会在项目的其他地方引起很多问题,特别是对于操作员而言.董事会和障碍.
我尝试过将对象作为const传递,然后使用Obstacle ob = new障碍物( const障碍物),但这使它们成为通用的Obstacle对象,而不是Player/Barrel/Wall对象.

是否有任何方法可以将这些对象作为非常量传递或将它们分配为非常量?我尝试使用const_cast(),但这导致了不确定的行为.

函数调用的示例:

  Board _-> setvalue(x,y,Player(data,moveable,x,y)); 

这是我的代码:

基类

 类障碍{上市:障碍* _正确初始化;字符串名称;bool可移动;int x;int y;障碍();障碍(字符串名称,布尔可移动,int x,int y);虚拟〜Obstacle();正确地boolInitialized();朋友std :: ostream&运算符<(std :: ostream& stream,Obstacle&Obstacle);}; 

派生类的示例(其他派生类尚无特殊功能)

  class播放器:公共障碍{上市:Player():Obstacle(){};播放器(字符串名称,布尔Momovable,int x,int y):障碍(名称,Moveable,x,y){this-&_; _ properlyinitialized = this;};〜Player(){};/* void Moveleft();void Moveright();void Moveup();void Movedown(); */}; 

Board类标题

 班级板{私人的:董事会* _正确初始化;整数长度int宽度;障碍* * *游乐场;上市:/*** ENSURE(this-> properlyInitialized(),调用对象时未初始化对象");*/木板();板子(整数长度,整数宽度);〜Board();正确地boolInitialized();/***需要(this-> properlyInitialized(),调用正确初始化时对象未初始化");*/void clear();const int getLength();const int getWidth();障碍*** getBoard();障碍* getTile(int length,int width);无效设置值(整数长度,整数宽度,障碍物和障碍物);朋友std :: ostream&运算符<(std :: ostream& stream,Board& Board);};std :: ostream&运算符<(std :: ostream& stream,Board& Board); 

最后是setvalue函数.

  void Board :: setvalue(整数长度,整数宽度,障碍物和障碍物){this-> playfield [length] [width] =& obstacle;//value;返回;} 

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

解决方案

让我们直接进入您提到的例程

,而不是进行完整的代码审查(-这不是SO的目的).

  void Board :: setvalue(整数长度,整数宽度,障碍物和障碍物){此-> playfield [长度] [宽度] =&障碍;返回;} 

设置三重指针

 障碍***运动场; 

这种设计不好有几个原因,但这是主要的设计:完全不清楚,当您想通过 Board :: playfield 调用障碍物时,它仍然存在.没有人能确保玩家不会被长期摧毁,而您很难确定这一事实.

相反,我建议您让董事会拥有障碍.因此,代替障碍原始指针,设置一个唯一指针向量,

  std :: vector< std :: unique< Obstacle>>游乐场 

,然后复制或移动课程:

  template< typename O>无效Board :: setvalue(int length,int width,O&&障碍物){playfield.push_back(std :: make_unique O(std :: forward O(障碍)));} 

(我已经将场几何放在一旁,我怀疑将其与障碍物的实际存储混合是否有用-但是如果您仍然愿意,可以使用向量的向量或带有向量的单个向量二维索引方案).

这又回到了您的意图:使用上述方法,您直接摆脱了所有的一致性问题.您又是. Board 拥有这些东西,并且可以随心所欲地对其进行处理.

I'm having trouble passing a derived class to a function which accepts the base class as argument. The base class is consists of "obstacles" which are to be placed on a "board" void Board::setvalue(int length, int width, Obstacle& obstacle);

However, this causes the compiler to give the "no known conversion for argument..."-error. Reading up around the site i found that i should be passing the derived object as a const, this however causes problems because a const can't be assigned to the board (since it holds pointers to non-const Obstacles).
In turn, changing Board to hold const Obstacles causes a lot of issues elsewhere in the project, especially with the operator<< of Board and Obstacle.
I have tried passing the objects as consts and then using Obstacle ob = new obstacle(the const obstacle) but this made them generic Obstacle objects rather than Player/Barrel/Wall objects.

Is there any way to pass these objects as non-consts or assigning them as non-consts? i tried using const_cast() but this caused undefined behaviour.

An example of the function call:

Board_->setvalue(x, y, Player(data, moveable, x, y));

Here is my code:

The base class

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);
};

An example of the derived classes (other derived classes don't have special functions yet)

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();*/
};

The Board class header

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);

And finally, the setvalue function.

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

I'm happy to provide more code if needed.

解决方案

Instead of a complete code review (-- which is not what SO is for), let's get directly to the routine you mentioned

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

which sets a triple pointer

Obstacle *** playfield;

This design is bad for several reasons, but here is the main one: it is not clear at all that the ostacle is still alive when you want to call it via Board::playfield. Nobody ensures that player isn't long destroyed, and you will be having a hard time in bookkepping this fact.

Instead, I suggest you to let the board own the obstacles. Thus, instead of an obstacle raw pointer, set up a vector of unique-pointers,

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

and then either copy or move the classes:

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

(I've left the field geometry aside, I doubt that it is useful to intermix it with the actual storage of the obstacles -- but if you still want to you can use a vector of vectors or a single vector with a two-dimensional index scheme).

And here back to your intention: With the above approach, you directly get rid of all constness problems. You aka. the Board owns the stuff and can do with it what you want.

这篇关于将派生类传递给基本函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆