Inheritance of protected class

81 Views Asked by At

I have a doubt with this code ( it is a question into a test so I don't need to change ):

class X {
    protected:
    int v;
};

class Y : protected X {
public:
    Y() : v(0) {}
    
};

int main()
{
    Y *y = new Y();
    cout << y->v;
    delete y;
    return 0;
}

I was quite sure that it was good because the v member of X was accessible from Y because Y was the subclass of a protected Class which has a protected member ( v ) but I have a compilation error. Can someone help me to understand? thanks!

2

There are 2 best solutions below

0
Vlad from Moscow On BEST ANSWER

There are at least two problems.

The first one is that the class definitions

class X {
    protected:
    int v;
};

class Y : protected X {
public:
    Y() : v(0) {}
    
};

are ijll-formed. From the C++17 Standard( 15.6.2 Initializing bases and members ):

2 In a mem-initializer-id an initial unqualified identifier is looked up in the scope of the constructor’s class and, if not found in that scope, it is looked up in the scope containing the constructor’s definition. [ Note: If the constructor’s class contains a member with the same name as a direct or virtual base class of the class, a mem-initializer-id naming the member or base class and composed of a single identifier refers to the class member. A mem-initializer-id for the hidden base class may be specified using a qualified name. — end note ] Unless the mem-initializer-id names the constructor’s class, a non-static data member of the constructor’s class, or a direct or virtual base of that class, the mem-initializer is ill-formed.

That is you may not use the non-static member v of the base class X as an initializing member in the ctor initialization of the class Y:

Y() : v(0) {}
      ^^^^

The second problem is that as the data member v is protected in the derived class Y then you may not directly access it outside the class as you are doing

cout << y->v;

Either make the data member public or create a public member function that will return the value of the data member v or a constant reference to the data member.

0
463035818_is_not_an_ai On

I was quite sure that it was good because the v member of X was accessible from Y...

Y has access to v. In your code you attempt to access it from main.

You misunderstand what it means to declare a protected member. It is not a mechanism to turn something that cannot be accessed from outside in a base class into something that everybody can access in a derived class. It merely gives the derived class access:

class X {
    public:
    X(int v) : v(v) {}
    protected:
    int v;
};

class Y :  public X {
public:
    Y() : X(0) {         // Base class initializes its members 
        std::cout << v;  // OK
    }    
};
    

Moreover you seem to conflate protected inheritance with making a member protected, and I removed it from the above. It does not change the fact that v cannot be accessed from outside and I consider it beyond the scope of the question. You should read about both: protected members and protected inheritance.


PS: Do not use manual dynamic memory allocation by default. Your main should be

Y y;
cout << y.v;

And it would have the exact same issue. If you do need to dynamically allocate something, use smart pointers to manage the lifetime.