1

I have

struct A { void ohai() {} };

struct B: protected A {};

struct C: private A { friend int main();};

struct D: B { void test() { ohai();} };

struct E: C { void test() { ohai();} };

int main() {
    A().ohai();
    B().ohai();
    C().ohai();
    D().ohai();    
    return 0;
}

However, I get the errors

error: ‘void A::ohai()’ is inaccessible
 struct A { void ohai() {} };
             ^
main.cpp:20:11: error: within this context
  B().ohai();
       ^
main.cpp:8:17: error: ‘void A::ohai()’ is inaccessible
 struct A { void ohai() {} };
             ^
main.cpp:22:11: error: within this context
  D().ohai();

I don't understand these errors. Because B inherits from A is protected, shouldn't it have access to Ohai? When I changed the inheritance to public, I got no errors

EDIT: Difference between private, public, and protected inheritance does not answer my question. According to that link, B should inherit ohai according to protected inheritance

Community
  • 1
  • 1
user5739619
  • 1,748
  • 5
  • 26
  • 40
  • 3
    `B` does but you do not. You just can't call `ohai` from a `B` instance. – NathanOliver Sep 30 '16 at 15:51
  • 1
    This is a duplicate, however I can understand why it is not clear to the OP. The misunderstanding in the code, is that while ohai() is accessible WITHIN B, as it has protected inheritance - it is not accessible from OUTSIDE B. That is - the line "B().ohai()" is now calling a protected function NOT a public one. –  Sep 30 '16 at 16:16

4 Answers4

1

The key about private, protected, and private, is understanding whether a class and its descendants understand that a class is subclassing something, versus whether external code to a class understands whether it is subclassing something.

Say we start with the class A:

struct A {
    void ohai() {};
};

Now B subclasses A with protected. That means that B and its inheritors understand that B is a type of A. Indeed, note how within the foo method, this is convertible to an A *:

struct B : protected A {
    void foo() {
        A *a = this;
    }
};

Now C subclasses B with public. Note how it also knows it is a type of A (because it knows it is a type of B, and it knows B is a type of A). We can again see that in its bar method:

struct C : public B {
    void bar() {
        A *a = this;
    }
};

Finally, D subclasses A publicly:

struct D : public A {
};

Up to now, we've considered how things look from inside the classes. Now let's see how they look on the outside.

Say we continue with:

int main() {
    A *p;

    A a;
    B b;
    D d;

Then, of course, p can point to &a.

    p = &a;

Since D subclasses A publicly, it can also point to &d.

    p = &d;

However, since B subclasses A protectedly, it does not know that it is a subclass of it. The following line fails compilation:

    p = &b;
}

It therefore leads to your error - it does not know that it is a subclass of it, and therefore doesn't know, from the side, that it has the ohai method.

Ami Tavory
  • 74,578
  • 11
  • 141
  • 185
0

This is because you are declaring A to be private in:

Struct C : private A{}

This makes A completely private and hence inaccessible to all of the structs accept C.

Anus Kaleem
  • 544
  • 4
  • 16
0

Function A::ohai() is accessible to class B and classes derived from B because of the protected inheritance. This is why D::test() is allowed to access ohai.

However, main() is not in the scope of class B or a class derived from B, so main() is not allowed to call B().ohai().

What matters for access checking is the function you're calling from, not the object you're calling on.

aschepler
  • 70,891
  • 9
  • 107
  • 161
0

you cannot access private and protected data or functions from outisde directly. to do so you need to have a Getter in public scope.

B has a copy of A so it has ohai() but under protected scope so objects of B cannot access ohai(). (protected and private are inaccessible from outside but only public).

so writing B().ohai() will issue in a compile-time error.

A().ohai(): A can access ohai() because ohai is public-scoped remember structs by default they have public access to members unlike classes which are private by default.

C: inherits privately from A so all members of A() (public, protected, private) will be under private scope in struct C so if you write try to access one of them will issue in an error: trying to access private data. BUT main() is declared as friend to C so it can access all members of C private, protected and public. (friend function have a full access to the all members which they are declared friend to) eg

friend ostream& operator << (ostream&, myClass &rhs); // this function can access all members of myClass

D: inherits publicly from B so all members of B EXCEPT private will be in D (remember private members are not inherited) and B inherits protectedly from A so B cannot access ohai() directly (protect) and thus D cannot access ohai() because ohai() in B is protected.

if you write:

D().test();// it's ok because test() in D is public and test() is a member of D so it can access ohai();

E: inherits publicly from C so E can access everything in C but private, C inherits privately from A so all members of A will be private in c so all these members in C inherited from A will not be inherited. so E cannot access ohai() because it is inherited privately in C.

Raindrop7
  • 3,889
  • 3
  • 16
  • 27