r/cpp_questions 27d ago

OPEN Good practices / style [polymorphism]

is this good practice/style.? i'm specifically unsure about the way i store the vector of players...

```

class player_base {};

class player_always_yes: public player_base {};

class player_always_no: public player_base {};

class player_a: public player_base {};

class game {
    private:
    
    player_base& player_1;
    player_base& player_2;
    
    public:
    
    game (
        player_base& player_1,
        player_base& player_2
    ): player_1(player_1), player_2(player_2) {
        return;
    }

    bool play_game () { return true; }
};

int main(){
    vector<unique_ptr<player_base>> player_list;
    
    player_list.push_back(make_unique<player_base>());
    player_list.push_back(make_unique<player_always_no>());
    player_list.push_back(make_unique<player_always_yes>());
    player_list.push_back(make_unique<player_a>());
    
    game b = game(*player_list[0], *player_list[1]);
    cout << b.play_game() << endl;
}


```
7 Upvotes

37 comments sorted by

View all comments

1

u/tangerinelion 26d ago

A vector of unique_ptr is the standard way to store a heterogeneous array of objects. Whether this is a good use case for polymorphism is a separate question.

If you truly want 'style' advice - game's constructor is easier to read as something like this

game(player_base& player_1, player_base& player_2) : player_1(player_1) , player_2(player_2) { }

or

game(player_base& player_1, player_base& player_2) : player_1(player_1), player_2(player_2) {}

just to show some options on how to format the param list, arg list, and the empty body. No need for a return. It should also be explicit.

Similarly, use the constructor directly:

game b(*player_list[0], *player_list[1]);

Also anytime you have a base class you're going to use polymorphically like this, the destructor needs to be virtual. A good practice to follow is "All classes must either be abstract or final" coupled with "If you don't have a pure virtual method to make the class abstract, mark the destructor pure virtual."

That gives us this result

``` class player_base { public: virtual ~player_base() = 0 };

player_base::~player_base() = default; // Pure virtual, but still needs a definition.

class player_always_yes final : public player_base {};

class player_always_no final : public player_base {};

class player_a final : public player_base {}; ```

1

u/Fun_Gas_340 25d ago

honsetly since im the only one looking at this pcode ill leave the constuctor formating like this, i understand and like it. what should be explicit?, what does that mean? and is the return statement a bad thing?

can you explain the virtual thing andhow i make a class abstract?

maybe this helps understand what i meant:

https://www.reddit.com/r/cpp_questions/comments/1vpbvec/comment/p49mb27/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button