1

The code below shows 2 classes person and trouble_maker. In this example i'm a bit confused why the trouble_maker class does not have access to set the variable name that it inherited from person directly in the instantiating list. Why does the trouble_maker object have to be created before i'm able to set the variable name?

#include <string>
class person {
    int age;
public:

    person(int age);
protected:
    std::string name;

};

person::person(int age) : age(age) {

}
class trouble_maker : person {
public:
    trouble_maker(std::string name, int age);
};

trouble_maker::trouble_maker(std::string name, int age) : person(age), name(name) //name is not a static memeber
{
    this->name = name; // works fine
}

int main() {
    person a_person();

    return 0;
}
Tanveer Badar
  • 5,438
  • 2
  • 27
  • 32
kino92
  • 39
  • 7
  • 1
    Also, because `trouble_maker` privately inherits `person`, a `trouble_maker` is-not-a `person`. (Can't be used for Liskov's substitution.) – Eljay Nov 23 '19 at 15:41
  • 1
    https://stackoverflow.com/questions/24079739/c-error-initializing-base-class-data-member-in-the-derived-class-member-initia (and dozens of others, i'm certain). – WhozCraig Nov 23 '19 at 15:42
  • It has access. You're just not doing it the right way. The `:` behind the constructor is for initialization of the class members only. You can call the base constructor however, but you have no constructor for name in the base. Assignment is possible in the constructor, but you need to put it between the braces. – JHBonarius Nov 23 '19 at 15:42
  • @whozcraig why didn't you flag duplicate, but only put the link? – JHBonarius Nov 23 '19 at 15:47

1 Answers1

4

The member intializer list following the : after the constructor head does not do any assignment of variables. Instead it specifies for each non-static direct data member and base class of the class an initializer with which these members or base classes are going to be initialized.

name is not a direct member of trouble_maker. It is not trouble_maker's job to initialize it. That is person's job.

Members and base classes are initialized top-down. First the bases class are initialized, then the direct members of the class. While the person subobject is created and initialized, the derived trouble_maker object doesn't even exist yet. Therefore it must be person that initializes name.

If you want to initialize name differently in trouble_maker than in person, you need to write a constructor for person that does the initialization for trouble_maker. trouble_maker can then call this constructor in the member initializer list, the same way you already do here: : person(age),.

The later this->name = name; is not initialization, but assignment. Since you made name protected rather than private, trouble_maker is allowed to assign to name, but it is still not able to initialize name without going through a constructor of person.

walnut
  • 21,629
  • 4
  • 23
  • 59