Search code examples
c++multiple-inheritance

C++ inherited parent calling all constructor overloads


I'm working through this course on udemy and I'm baffled at this output.

The default parent constructor for Creature() is called even when I call the constructor through the child's constructor. I've been in JavaScript land the last 8 years so I've seen some wacky stuff, but I'm not sure how I'm accident pull this off.

P.S. I know this isnt pretty code, its for the course.

#include <iostream>;
#include <string>;

using namespace std;

class Creature
{
public:
    Creature();
    Creature(string name, float health);

    string Name;
    float Health;
};

class Dragon:public Creature
{
public:
    Dragon();
    Dragon(string name, float health);
};

int main()
{
    Dragon dragon2("Smaug", 100.f);
    cout << "The Dragon's name should be Smaug: " << dragon2.Name << endl;
    
    return 0;
}
 
Creature::Creature(string name, float health)
{
    Name = name;
    Health = health;
    cout << "Creature constructor WITH arguments" << endl;
};

Creature::Creature() 
    : Name("UNAMED"), Health(100.f)
{
    cout << "Creature constructor with NO arguments" << endl;
}

Dragon::Dragon(string name, float health)
{
    Creature(name, health);
    cout << "Dragon constructor WITH arguments" << endl;
}

Dragon::Dragon()
{
    cout << "Dragon Constructor with NO arguments" << endl;
}

Output:

Creature constructor with NO arguments
Creature constructor WITH arguments
Dragon constructor WITH arguments
The Dragon's name should be Smaug: UNAMED

I understand (sorta) why and how default constructors would be called, but I expected the output to be:

Creature constructor WITH arguments
Dragon constructor WITH arguments
The Dragon's name should be Smaug: Smaug

Solution

  • This is wrong:

    Dragon::Dragon(string name, float health)
    {
        Creature(name, health);
        cout << "Dragon constructor WITH arguments" << endl;
    }
    

    Well, it is syntactically correct but it is not doing what you think it does. Creature(name,health); calls the constructor of Creature to create a temporary that lives till the end of that line. You see the default constructor getting called because you do not call the Creature constructor for the Dragon that is being constructed, hence the Creature part of the Dragon is default constructed.

    To call the base constructor:

    class Dragon : public Creature
    {
    public:
        Dragon();
        Dragon(string name, float health) : Creature(name,health) {
            cout << "Dragon constructor WITH arguments" << endl;
        }
    };