【问题标题】:Is this the correct way to use an array of abstract class (C++)?这是使用抽象类(C++)数组的正确方法吗?
【发布时间】:2011-12-09 19:56:55
【问题描述】:

忽略我使用原始指针/数组的事实。

我正在用 C++ 制作一个纸牌游戏,它有一个由其他类扩展的 Player 抽象类。我需要创建一个指向这些派生类的指针数组。这可行,但有更好的方法吗?

class Player{
   public:
        Player();
        Player(const Player&);
        Player & operator=(const Player &);

        virtual void sort() = 0;
        virtual Card play(Pile*) = 0;

        void confirmPlay();

        void giveHand(Hand&);
        void giveCard(Card);
        bool hasCards();

        void won();
        void resetWins();
        int getWins();

        virtual ~Player();
    protected:
        int cardsLeft;
        Hand hand;
        int cardPlayed;
        int wins;
    private:
};

class DumbPlayer : public Player
{
    public:
        DumbPlayer();
        Card play(Pile*);
        void sort();
        virtual ~DumbPlayer();
        DumbPlayer & operator=(const DumbPlayer &);
        DumbPlayer(const DumbPlayer&);
    protected:
    private:
};

class Game{
    public:
        Game(int,  Player**&);
        void playX(int);
        void playOne();
        virtual ~Game();
    protected:
    private:
        bool done();
        Game & operator=(const Game &);
        Game(const Game&);
        Pile * piles;
        Deck deck;
        int playerCount;
        Player ** players;
};

//implementation not shown to save space, tell me if you would like to see anything.
//I think that all of the other class/function names should be good enough to not show.

Game::Game(const int pplayerCount, Player**& pplayers) : 
                                   piles(new Pile[4]), 
                                   playerCount(pplayerCount), 
                                   deck(), 
                                   players(new Player*[playerCount]){
    for(int i = 0; i < 4; i++){
        piles[i].setSuit(i);
    }

    for(int i = 0; i < playerCount; i++){
        players[i] = pplayers[i];
    }
}

void Game::playOne(){
    deck.shuffle();  //shuffle deck
    for(int i = 0; i < 4; i++){
        piles[i].reset();  //reset piles
    }
    Hand hands[playerCount];  //create hands
    Hand leftovers;
    deck.dealAll(playerCount, hands, leftovers); //deal the deck
    int cardsLeftover = leftovers.getSize();     //there are leftover cards, 
                                                 //52/3 has a remainder
    for(int playerIdx = 0; playerIdx < playerCount; playerIdx++){
        (*players[playerIdx]).giveHand(hands[playerIdx]); //this is what 
                                                          //i am unsure about.
        (*players[playerIdx]).sort();
    }
    int winner = -1;
    while(!done()){
        for(int playerIdx = 0; playerIdx < playerCount; playerIdx++){
            Card play = (*players[playerIdx]).play(piles);
            if(piles[play.getSuit()].canPut(play)){
                (*players[playerIdx]).confirmPlay();
                piles[play.getSuit()].put(play);
                if(!(*players[playerIdx]).hasCards()){
                    winner = playerIdx;
                    break;
                }
            } else {
                if(cardsLeftover > 0){
                    (*players[playerIdx]).giveCard(leftovers.popCard(--cardsLeftover));
                }
            }
        }
        if(winner != -1){
            (*players[winner]).won();
            break;
        }
    }
}

我知道这是一大堆代码(对于这个网站)...我不确定游戏构造函数/类以及包括 (*players[i]).x() 在内的行。

【问题讨论】:

  • 不要使用原始指针。不要使用原始数组。请务必使用标准库元素。
  • 我仍然不清楚你的问题,但如果你只是对(*players[i].x()) 语法感到不安,你可以改用players[i]-&gt;x() 来清理它。除此之外,您对忽略您使用原始指针和数组这一事实的评论有点误导恕我直言——您问我们可以做些什么来改进您的代码,而智能指针和向量是您的重要组成部分可以让它更健壮。

标签: c++ class pointers polymorphism abstract-class


【解决方案1】:

现在,指针数组被拼写:

std::vector<boost::shared_ptr<Player> > players;

这需要完整的Resource Acquisition Is Initialization (RAII) idiom,以确保正确调用析构函数并在遇到异常和不可预见的代码路径时回收内存。

【讨论】:

  • 首选 boost::ptr_vector 它不仅管理指针。但是它将其元素公开为对对象的引用。因此,将其与标准算法一起使用要简单得多。
  • 我总是忘记 ptr_containers。谢谢提醒!
  • 为什么这样更好?析构函数不是总是在异常之后调用吗?还是不是?
  • 当然,但是指针的析构函数(即无操作)而不是指向对象的析构函数。更不用说没有删除来释放使用的内存。 std::vector 将数组的释放逻辑放入其析构函数中,而 boost::shared_ptr 将指向的对象的删除/销毁逻辑放入其析构函数中。
  • @Drew 接受您对主要问题的评论,这就是我要问的。我还将使用 std::vector/boost::shared_ptr
【解决方案2】:

使用 std::vector、list、map 等

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-15
    • 1970-01-01
    • 2014-02-16
    • 2011-02-04
    • 2013-08-13
    • 1970-01-01
    • 2016-05-10
    • 2012-05-11
    相关资源
    最近更新 更多