9

Why would the following code run into error of ‘A’ is an inaccessible base of ‘B’? Here's my thoughts:

  • whenever we call function foo(), it will execute new B(5), which will first call the constructor of its base struct A.

  • struct A's constructor function is a public method, hence it should be accessible by its derived struct B (as protected if i'm not wrong).

  • then struct B's constructor function will be call to create a vector with five 0s.

  • then deleting object a will call destructor B, then destructor A.

Is there anything wrong with my logic? Your answer will be greatly appreciated

#include <iostream>
#include <vector>

using namespace std;

struct A 
{ 
    A() { cout << "Constructor A called"<< endl;} 
    virtual ~A() { cout << "Denstructor A called"<< endl;}
};

struct B : private A
{
    vector<double> v;
    B(int n) : v(n) { cout << "Constructor B called"<< endl;}
    ~ B() { cout << "Denstructor B called"<< endl;}
};

int main()
{
    const A *a = new B(5);
    delete a;

    return 0;
}
skratchi.at
  • 1,151
  • 7
  • 22
Jeremy
  • 379
  • 2
  • 11
  • 2
    Because you made inheritance `private`, noone from the outside knows that this inheritance *exists*. So from the outside, `A` and `B` are unrelated types. – Yksisarvinen Nov 18 '19 at 10:41

2 Answers2

11

There's nothing wrong with your logic, except that it's missing one point:

private inheritance basically means that only the inheriting class (B in this case) knows that it inherits from the base A. That in turn means that only B can make use of all the privileges that come with this inheritance. One of these privileges is to be able to cast B* to A*. The function foo() doesn't know about B's inheritance, so it cannot perform that cast.

sebrockm
  • 5,733
  • 2
  • 16
  • 39
  • 1
    Worth noting, the same problem happens with `protected` inheritance as well. In short, it's not just because it's `private`; more generally, it's because its *not* public nor friended (and yes, you *can* `friend void foo();` within `B`, thereby granting `foo` access to `B`'s protected or private inheritance to `A` and thus make both cases *work*). – WhozCraig Nov 18 '19 at 10:50
  • @WhozCraig right. Also worth noting, there is no difference in how access qualifiers work for members and inheritance: When you declare a member `public`, `protected`, or `private`, you specify who can access this member and who can't. When you declare an inheritance `public`, `protected`, or `private`, you specify who can "access" this inheritance and who can't, i.e. who can make use of it (e.g. performing casts or access base class members). In both cases it's the very same rules that either grant you access or not. – sebrockm Nov 18 '19 at 11:04
0

TL;DR

You are deriving B as 'private' from A. You must change it to

struct B : public A{
    vector<double> v;
    B(int n): v(n) {std::cout << "B Constructor" << std::endl};
    ~B() {std::cout << "B Destruktor" << std:.endl;};
};

Extended explanation

By using private inheritance you define B has a A instead of B is a A. With a has-a dependency you cannot up- and downcast between both classes (Apple cannot become a worm and vice versa. Even if an apple has a worm).

You mainly use private inheritance if you want to take advante of features implemented by another class, without exposing the public Inteface of the used class. For e.g. You could use features of a parser inside your class without being a parser on your own.

A.K.
  • 861
  • 6
  • 12