使用继承的函数而不是基函数(不是抽象函数)

Using inherited function instead of the base (not abstract)

本文关键字:基函数 抽象函数 继承 函数      更新时间:2023-10-16

例如,我想要名为chessmanpawn的类。我不能让chessman成为一个抽象类,因为我需要创建它的2D数组。pawn类继承了chessman,当我写这个时,我需要使用pawnmove函数:

chessman *cm = new pawn("a3", 'w');
cm->move(pos);

此代码使用chessman::move。我能做些什么让它使用pawn类中的那个?我的问题与这个问题非常相似,但我的函数不将pawn作为自变量。在Java中,这很容易,因为您可以创建抽象类的数组,但在C++中,这只是令人困惑。

编辑:

以下是棋子类的定义(正如你所看到的,功能已经是虚拟的):

class chessman
{
public:
    int i;
    int j;
    string name;
    char color;
    virtual bool move(string final_pos);
};

和典当:

class pawn : public chessman
{
public:
    pawn(string pos, char color);
    bool move(string final_pos);
};

我不能让棋子成为一个抽象类,因为我需要创建一个二维数组。

是的,你可以。您不创建chessman对象的数组,而是创建指向chessman对象的指针的数组。那么chessman可以是抽象的(因为不应该从一开始就直接创建chessman的实例)。

典当类继承了棋子,当我写这个时,我需要使用典当的移动功能

多态性为你处理这些。但是,为了使用多态对象数组,数组需要保存指向存储在内存其他地方的对象的指针/引用,而不是保存实际对象本身。

在Java中,这很容易,因为您可以创建抽象类的数组,但在C++中,这只是令人困惑。

你在C++中也可以做同样的事情。在Java中,对象是引用类型,因此它们总是由指针引用(Java语言只是对您隐藏了这些细节)。

试试这样的东西:

class chessman
{
private:
    virtual bool isValidMove(string final_pos) = 0;
public:
    int i;
    int j;
    string name;
    char color;
    chessman(string aname, char acolor);
    bool move(string final_pos);
};
chessman::chessman(string aname, char acolor)
    : name(aname), color(acolor)
{
}
bool chessman::move(string final_pos)
{
    // validate that final_pos is a valid position on the board...
    // validate that final_pos is a valid position for the piece being moved...
    if (!isValidMove(final_pos))
        return false;
    // move to the position...
    return true;
}

class pawn : public chessman
{
private:
    virtual bool isValidMove(string final_pos);
public:
    pawn(string pos, char color);
};
pawn::pawn(string pos, char color)
    : chessman("pawn", color)
{
    //...
}
bool pawn::isValidMove(string final_pos)
{
    // validate that final_pos is a valid position for this pawn to move to...
    return ...;
}

class rook : public chessman
{
private:
    virtual bool isValidMove(string final_pos);
public:
    rook(string pos, char color);
};
rook::rook(string pos, char color)
    : chessman("rook", color)
{
    //...
}
bool rook::isValidMove(string final_pos)
{
    // validate that final_pos is a valid position for this rook to move to...
    return ...;
}

class knight : public chessman
{
private:
    virtual bool isValidMove(string final_pos);
public:
    knight(string pos, char color);
};
knight::knight(string pos, char color)
    : chessman("knight", color)
{
    //...
}
bool knight::isValidMove(string final_pos)
{
    // validate that final_pos is a valid position for this knight to move to...
    return ...;
}

class bishop : public chessman
{
private:
    virtual bool isValidMove(string final_pos);
public:
    bishop(string pos, char color);
};
bishop::bishop(string pos, char color)
    : chessman("bishop", color)
{
    //...
}
bool bishop::isValidMove(string final_pos)
{
    // validate that final_pos is a valid position for this bishop to move to...
    return ...;
}

class queen : public chessman
{
private:
    virtual bool isValidMove(string final_pos);
public:
    queen(string pos, char color);
};
queen::queen(string pos, char color)
    : chessman("queen", color)
{
    //...
}
bool queen::isValidMove(string final_pos)
{
    // validate that final_pos is a valid position for this queen to move to...
    return ...;
}

class king : public chessman
{
private:
    virtual bool isValidMove(string final_pos);
public:
    king(string pos, char color);
};
king::king(string pos, char color)
    : chessman("king", color)
{
    //...
}
bool king::isValidMove(string final_pos)
{
    // validate that final_pos is a valid position for this king to move to...
    return ...;
}

然后你可以做这样的事情:

chessman* white_pieces[16];
chessman* black_pieces[16];
for (int i = 0; i < 8; ++i)
{
    white_pieces[i] = new pawn(...);
    black_pieces[i] = new pawn(...);
}
for (int i = 8; i < 10; ++i)
{
    white_pieces[i] = new rook(...);
    black_pieces[i] = new rook(...);
}
for (int i = 10; i < 12; ++i)
{
    white_pieces[i] = new knight(...);
    black_pieces[i] = new knight(...);
}
for (int i = 12; i < 14; ++i)
{
    white_pieces[i] = new bishop(...);
    black_pieces[i] = new bishop(...);
}
white_pieces[14] = new queen(...);
black_pieces[14] = new queen(...);
white_pieces[15] = new king(...);
black_pieces[15] = new king(...);

并根据需要移动它们:

white_pieces[index]->move(pos);
...
black_pieces[index]->move(pos);

当然,完成后不要忘记清理:

for (int i = 0; i < 16; ++i)
{
    delete white_pieces[i];
    delete black_pieces[i];
}

若要自动进行清理,可以使用std::auto_ptr<chessman>对象的数组。或者,在C++11及更高版本中,std::unique_ptr<chessman>对象的std::vector/std::array

在C++中,您可以创建一个指向棋子的某种指针(指针类型由对象所有权决定)的vector(或可能在C++11中创建array),并使棋子抽象。这只是一种稍微不同的思考方式。

(根据评论意见进行编辑):要使它选择合适的move函数,请使用基类中的virtual机制。我建议通过不具有公共虚拟功能来将接口与实现分离。相反,请使用公共非虚拟接口和私有或受保护的虚拟实现。您将使用一个私有实现,每个子类完全替换该功能,而当子类也需要调用父功能时,您将使用protected。