我希望有一个名为chessman
和pawn
的课程。我不能让西洋棋棋子成为一个抽象类,因为我需要创建一个2D数组。 pawn
类继承chessman
,当我写这篇文章时,我需要使用move
pawn
函数:
chessman *cm = new pawn("a3", 'w');
cm->move(pos);
此代码使用chessman::move
。我该怎么做才能使它来自pawn
类?我的问题与this question非常相似,但我的函数并没有将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);
};
答案 0 :(得分:3)
我不能让西洋棋棋子成为一个抽象类,因为我需要创建一个2D数组。
是的,你可以。您没有创建chessman
个对象数组,而是创建一个指向 chessman
个对象的数组。然后chessman
可以是抽象的(因为它应该是,因为您不应该直接创建chessman
的实例)。
pawn类继承了西洋棋棋子,当我写这个
时我需要使用pawn的move函数
多态性为您处理。但是为了使用多态对象数组,数组需要保存指向存储在别处的对象的指针/引用,而不是自己保存实际的对象。
在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::vector
/ std::array
个std::unique_ptr<chessman>
个对象。
答案 1 :(得分:1)
在C ++中,你会在棋盘上创建一个vector
(或者在C ++ 11中可能是array
的某种指针(指针类型由对象所有权决定),并且西洋棋棋子是抽象的。这只是一种略微不同的思考方式。
(编辑评论很有意思):
要使其选择正确的move
函数,请使用基类中的virtual
机制。我建议通过不使用公共虚函数将接口与实现分开。而是使用公共非虚拟接口和私有或受保护的虚拟实现。您将使用私有实现,每个子代完全替换功能,而当子类需要也调用父功能时,您将使用protected。