调用虚方法而不是派生方法

时间:2015-06-10 11:05:43

标签: c++ inheritance object-slicing

我在继承功能方面遇到了麻烦,我似乎无法弄清楚为什么它的行为方式如此,并且无法在SO上的其他问题中找到答案。
我正在开发一个小游戏,并且继承的函数负责玩家和对象之间的交互,如果玩家试图移动到已经由“障碍”的各种子类之一居住的空间,它将调用该对象的“Bool GetMove”方法,然后执行其唯一规则,如果游戏可以将玩家放置在空间上,则返回True;如果不能,则返回False。

这是基类头及其getmove方法:

class Obstacle
{
public:
    const char* id;
    Obstacle* _properlyinitialized; //a pointer that points to the object itself, required by the teacher who gave the assignment.
    string Name;
    mutable 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);
    virtual bool getmove(const char*, std::vector<std::vector<std::vector<Obstacle> > >&);
    virtual void leavetile(std::vector<std::vector<std::vector<Obstacle> > >&);
};

bool Obstacle::getmove(const char* direction,std::vector<std::vector<std::vector<Obstacle> > >& _board){
    cout << "wrong getmove" << endl; //this method should never be called.
    return true;
};

其中一个继承类及其getmove方法:

class Barrel: public Obstacle
{
public:
    Barrel():Obstacle(){};
    Barrel(string Name, bool Moveable, int x, int y);
    ~Barrel(){};
    bool getmove(const char*, std::vector<std::vector<std::vector<Obstacle> > >&);
    void leavetile(std::vector<std::vector<std::vector<Obstacle> > >&);
};

bool Barrel::getmove(const char* direction,std::vector<std::vector<std::vector<Obstacle> > >& _board){
    cout << "barrel getmove" << endl;
    if(strcmp(direction, "OMHOOG") == 0){ //what direction to move?
        if(_board[this->x][this->y-1][0].properlyInitialized()){ //is that object already inhabited by an object?
            if(_board[this->x][this->y-1][0].Moveable){ //can the object be moved?
                if(_board[this->x][this->y-1][0].getmove(direction, _board){//move the object
                    _board[this->x][this->y-1][0] = *this; //move the barrel
                    _board[this->x][this->y-1][0]._properlyinitialized = &_board[this->x][this->y-1][0];
                    return true; //return true
                }
                else{
                    return false; //an object is in the way, the barrel can't be moved
                }
            }
            else{
                return false; //an object is in the way, the barrel can't be moved
            }
        }
        else{
            _board[this->x][this->y-1][0] = *this; //move the barrel
            _board[this->x][this->y-1][0]._properlyinitialized = &_board[this->x][this->y-1][0];
            return true; //return true
        }
    } //This is for direction "up", i left the other directions out because they're almost equal.

该方法调用如下:

//"this" is a board object
if(this->playfield[this->_player->x][(this->_player->y)-1][0].getmove(direction, this->getBoard())){
    //do some stuff
}

我曾考虑将Obstacle对象更改为纯虚拟对象,但我需要在其他位置使用虚拟“障碍”对象,因此这不是一个选项。

1 个答案:

答案 0 :(得分:2)

getmove的第二个参数应该是

std::vector<std::vector<std::vector<Obstacle*>>>&

请注意,最里面的向量是Obstacle*而不是Obstacle?这样就可以调用正确的虚函数,更重要的是,你不会遇到object slicing