在C ++中,继承超类的正确方法是什么,以便它们的子类在超类和子类中不具有重复属性?

时间:2015-05-20 04:13:09

标签: c++ inheritance

以下代码是我尝试做的简单示例。目标是在超级类中拥有所有游戏逻辑。然后,在必要时,为平台特定功能添加子类。

#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 ++中是否可行?在这种情况下是否需要董事会指针?我错过了一些明显的东西吗

2 个答案:

答案 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一起使用。