以下代码是我尝试做的简单示例。目标是在超级类中拥有所有游戏逻辑。然后,在必要时,为平台特定功能添加子类。
#include <iostream>
// Base Game and GameBoard classes to handle all of the core logic
class GameBoard
{
public:
GameBoard();
void performMove(int value);
protected:
int board[4][4];
};
class Game
{
public:
Game();
GameBoard gameBoard;
void performMove(int value);
};
// Derived Game and GameBoard classes to handle the user interaction IO.
class DerivedGameBoard : public GameBoard
{
public:
DerivedGameBoard();
void print();
};
class DerivedGame : public Game
{
public:
DerivedGame();
DerivedGameBoard gameBoard;
};
Game::Game() {
gameBoard = GameBoard();
}
void Game::performMove(int value) {
gameBoard.performMove(value);
}
DerivedGame::DerivedGame() {
gameBoard = DerivedGameBoard();
}
GameBoard::GameBoard()
{
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
board[i][j] = 0;
}
}
}
void GameBoard::performMove(int value)
{
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
board[i][j] = value;
}
}
}
DerivedGameBoard::DerivedGameBoard()
{
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
board[i][j] = 1;
}
}
}
void DerivedGameBoard::print()
{
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
std::cout << board[i][j];
}
std::cout << std::endl;
}
}
这是我测试这些类交互的地方。我的假设或期望的输出在评论中。
int main(int argc, char** argv)
{
std::cout << "Test Derivation" << std::endl;
DerivedGame game = DerivedGame();
game.gameBoard.print(); // Prints all 1s as expected
game.gameBoard.performMove(2);
game.gameBoard.print(); // Prints all 2s as expected
game.performMove(3);
game.gameBoard.print(); // Prints all 2s, which is unexpected.
}
这种继承在C ++中是否可行?在这种情况下是否需要董事会指针?我错过了一些明显的东西吗
答案 0 :(得分:3)
这就是The Way(大写,因为非常重要)
class Base
{
virtual BaseAttr& getAttr() = 0;
// methods that use getAttr
};
class Derived final : public Base
{
// Covariant return type
DerivedAttr& getAttr() override {
return attr;
}
// more methods that use getAttr
DerivedAttr attr;
};
这种设计有时被称为&#34;智能儿童设计模式&#34;。
重要的是要注意你的基类是抽象的,你的具体类是final的(不再进一步派生)。这实际上是一个总是这样做的好习惯。这种设计风格的一种极端形式是仅从纯接口(a.k.a。纯抽象类)公开派生。
答案 1 :(得分:2)
首先,如果可能,我想说要避免这种整体设计。新的C ++程序员过度使用继承,这里你有一个带有vtable的类层次结构,你实际上并不需要它,这会增加许多不必要的复杂性。
无论如何,如果派生类需要不同的gameBoard
,那么你将不得不通过基类指针(或引用)访问该板,这样你就可以为每个游戏类实际分配不同的板类。
有几种方法可以解决这个问题;这是一个可能的骨架:
struct BasicGame
{
std::unique_ptr<BasicBoard> p_board;
BasicGame(BasicBoard *new_board): p_board(new_board) {}
virtual ~BasicGame() = 0; // make this abstract
};
struct Game1 : BasicGame
{
Game1(): BasicGame{ new Board1 } {}
};
struct Game2 : BasicGame
{
Game2(): BasicGame{ new Board2 } {}
};
这样,当您构建Game2
时,p_board
指向Board2
类型的板(当然必须从BasicBoard
派生,并且有虚拟功能);接受BasicBoard
引用的函数将能够与p_board
一起使用。