Why can't I access inherited protected fields in a derived constructor's member initialization list?

Viewed 161

I'm new to OOP. I recently learned some things about Inheritence in C++, and that a protected field can't be accessed from outside of the class, but it can be accessed in inherited classes. I have some problems with my code and I don't understand what is wrong:

class Base
{
protected:
    int x;
    int y;
    int z;
public:
    Base(int a, int b): x(a), y(b) { cout << "Base constructor" << endl; };
    Base(const Base& prev) : x(prev.x), y(prev.y) { cout << "Base copy constructor" << endl; };

    void print_x()
    {
        cout << x << endl;
    }

    void print_y()
    {
        cout << y << endl;
    }

    ~Base() { cout << "Base destructor" << endl; };
};

class Derived : public Base
{
public:
    Derived(int a, int b): x(a), y(b) { cout << "Derived constructor" << endl; };    ////////ERROR : Class 
 'Derived' does not have any fields named 'x' and 'y'
};

int main()
{
    Base* b = new Base(10, 20);
    Derived* d = new Derived(10, 20);
    delete b;
    delete d;
    return 0;
}

If Derived inherits Base, why does the compiler say that Derived doesn't have the fields x and y?

1 Answers

You can access them in Derived, but they are members of Base and cannot be initialized directly in the member initialization list of Derived. This also wouldn't work if they were public. Note that the Base class is initialized before the members of Derived are initialized.

To initialize the base, you can call its constructor in the Derived's member initialization list:

class Derived : public Base
{
  public:
      Derived(int a, int b) : Base(a, b)  {  }; 
};

For more details, see here: https://en.cppreference.com/w/cpp/language/constructor

PS: Note that with respect to the member initialization list, there is also no difference to members that are private in the base. All members of the base are inherited, and initialized before members of the derived are initialized.

You miss to initialize z, and in your example there is no reason to use new and delete. If you fix the above, you get same output with this code:

int main()
{
    Base b(10,20);
    Derived d(10,20);
}

Last, but not least, if you plan to use Derived polymorphically, you need to declare the destructor of Base as virtual.

Related