pointers to derived and base classes

I'm doing some ongoing work on a project, the card game "War," and I've run into a strange situation that I hope to get some clarification on.
class Player is an ABC, and both class Human and class Computer are publically derived from it. The question I have is with lines 17 and 18, and the function starting on line 45.

I know that pointers to base classes can be implicitly upcast to pointers to their derived classes, and Player* player_choice(); is defined to return a pointer to Player, but the actual return statements in the function body all return objects of the derived classes. Also, all the programming books I've read state that the statements on lines 17 and 18 should assign the pointers to the address of an object.

If I had to guess, I would say that the function player_choice() returns an object of a derived class, it is cast to a pointer-to-Player, and the lvalue pointer is assigned to the rvalue return pointer. If anyone can shed some light on this mystery, it would be greatly appreciated.

For what it's worth, this program compiles and runs as it is. Currently running C::B with MinGW on WIN XP. I tested with some chatty constructors and destructors, and they're all called in order and when they're supposed to.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <iostream>
#include <string>
#include "deck.h"

void rules_of_the_game();
Player* player_choice();

int main()
{
    using std::cout;
    using std::endl;
    using std::string;

    cout << "This program simulates the card game, \"War\"\n";
    //will add the text explaining the rules later.
    rules_of_the_game();
    Player* p1 =  player_choice();
    Player* p2 =  player_choice();

    p1->initializeDeck();
    p2->initializeDeck();

    cout << "Player 1 has " << p1->countDeckSize() << " cards." << endl;
    cout << "Player 2 has " << p2->countDeckSize() << " cards." << endl;

    cout << "Contents of player 1 deck:" << endl;
    p1->displayCards();
    cout << endl;

    cout << "Contents of player 2 deck:" << endl;
    p2->displayCards();
    cout << endl;

    delete p1;
    delete p2;

    return 0;
}

void rules_of_the_game()
{
    std::cout << "rules go here." << std::endl;
}

Player* player_choice()
{
    using std::cout;
    using std::string;
    string player_name = "";

    static int current_player_number = 1;

    cout << "Will player " << current_player_number << " be a person or the computer?\n";
    cout << "Enter 'p' for person, 'c' for computer:\n";
    char player_type;
    std::cin >> player_type;
    std::cin.ignore(255,'\n');
    if(player_type=='p')
    {
        cout << "Please enter the name of player #" << current_player_number << ": ";
        getline(std::cin, player_name);
        current_player_number++;
        return  new Human(player_name);

    }
    else if(player_type=='c')
    {
        cout << "Please enter the name of computer player #" << current_player_number << ": ";
        getline(std::cin, player_name);
        current_player_number++;
        return new Computer(player_name);

    }
    else
    {
        cout << "Incorrect type. Defaulting to human player\n";
        cout << "Please enter the name of player #" << current_player_number << ": ";
        getline(std::cin, player_name);
        current_player_number++;
        return new Human(player_name);
    }
}
Last edited on
atropos wrote:
class Deck is an ABC, and both class Player and class Computer are publically derived from it.
Does this make sense? With public inheritance you're saying:
Deck is an ABC
Player is a Deck
Computer is a Deck

Are players actually decks? Or do they have decks?
Perhaps choosing the name of the base class as "Deck" was foolish on my part, but yes, a Player is a type of Deck. I'll go back and change the names to
1
2
3
class Player {...} //ABC
class Human : public Player {...}
class Computer : public Player {...}

The reason for the strange names is that originally, there was only one class, Deck. As time went by, Deck became a base class, and finally an ABC. I forgot to change the class names to better reflect the roles they play in the program
Last edited on
Ah, that makes sense.

To answer your question.
atropos wrote:
If I had to guess, I would say that the function player_choice() returns an object of a derived class, it is cast to a pointer-to-Player, and the lvalue pointer is assigned to the rvalue return pointer.
Not really. Recall that new returns a pointer to the memory it allocated. You're implicitly casting a pointer to a derived type to a pointer to the base class, not an actual instance of a derived class to a pointer to a base class.

Consider this code:
1
2
3
4
5
int GetNumber()
{
    short x = 7;
    return x; //implicitly casting to int
}
Do you understand this code? If so, now look at this:
1
2
3
4
5
Human *getHuman()
{
    Player *p = new Player;
    return p; //implicitly casting to Human *
}
Remember, p is a pointer to a player, not an actual player. The function returns a pointer to a human, not an actual human. A player is a human, so it is perfectly fine to point to a player with a human pointer, because it is-a player. This is polymorphism at work ;)
Last edited on
L B wrote:
Recall that new returns a pointer to the memory it allocated...

Well, I do now :P

new has always confused me, on account of there's 3 of them :/

Thank you so much for that expanation.
operator new - allocates memory but does not call constructor
placement new - calls constructor but does not allocate memory
new - plain and simple, does both


I can see how it can be confusing, but in all three cases, a pointer is returned.
Topic archived. No new replies allowed.