1

I came across this question while experimenting with following simple code.

#include <iostream>
using namespace std;

class A{
    public:
    A(){ cout << "Def contr A" << endl; }
    ~A(){ cout << "Def destr A" << endl; }
};

class B : protected A{
    public:
    B(){ cout << "Def contr B" << endl;}
    ~B(){ cout << "Def destr B" << endl; }   
};

int main() {
    A* a_p = new B();
    return 0;
}

I got following error error: 'A' is an inaccessible base of 'B'

By referring this & this , I found that details of base class A are not visible outside of class scope of B and B* is implicitly casted into a A*.

But my question is, compiler already knows the definition and layout of A. Why it is giving an error. My assumption is, even though compiler knows the definition of A, it doesn't know it is safe to cast B* into A* since inherited data is not visible.

Can someone help me to understand what really happens here?


Just to make the question more clear, Lets say we have another class C which is not inheriting from A.

Then I can easily do A* a = (A*) new C(); this without an error.

Why this is allowed and why A* a_p = new B(); is not allowed? What is the difference between these two scenarios?

e11438
  • 864
  • 3
  • 19
  • 33
  • `protected` - take a look. – 273K Jul 29 '22 at 05:52
  • Sure, the compiler knows, and you _can_ assign `B*` to `A*` within the context of class B. Anything _outside_ of that context does not have access to such a conversion because it's not public. The rules are enforced by the compiler to prevent misuse of the class as per its intended design. – paddy Jul 29 '22 at 05:55
  • @273K Yes I understand that, even that is inherited as protected compiler knows the definition of A, isn't it? – e11438 Jul 29 '22 at 05:55
  • `B` is inheriting `A` as a `protected` base. Change it to `public` to allow conversion from `B*` to `A*`. – wohlstad Jul 29 '22 at 05:55
  • Do you know how secrets work? – molbdnilo Jul 29 '22 at 05:56

1 Answers1

1

With the inheritance line

class B : protected A

You are basically saying, "inherit from A and make all it's public members inaccessible from outside and only accessible from B itself.

You kind of protect the members of A, including its constructors.

So you cant construct an instance of A from outside B anymore, but you can from within B or B itself.

So this will compile:

B *a = new B;

it's the same as having private constructors in the first place so this would not compile either.

class A {
  private:
    A() {}
};

int main() { A *a = new A; }
Serve Laurijssen
  • 9,266
  • 5
  • 45
  • 98
  • Lets say we have another class `C` which is not inheriting from `A`. Then I can easily do `A* a = (A*) new C();` this without an error. why this allowed and one in the question is not allowed. – e11438 Jul 29 '22 at 06:15
  • 1
    thats just language rules. with casting you can turn any object into any object. But if your code crashes after its your own fault. with protected inheritance your code will look clean and follow language rules which will not crash. – Serve Laurijssen Jul 29 '22 at 06:22