This question already has answers here:
private inheritance
(6 answers)
What is the difference between public, private, and protected inheritance in C++?
(16 answers)
Closed 3 years ago.
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;
}
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.
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.
Related
Until today I thought I understood inheritance much better than I apparently do. The goal here with this example was to design a framework of n number of classes (3 in this case), which should each exist uniquely for the life of the program. The forth class, whose implementation would contain the global main function would be responsible handling memory for the other classes. In addition, I was hoping to keep public members in the base classes protected, to prevent any other class from calling them.
Currently, the inheritance in the "Main" class is commented out as well as "protected:" keywords in each of the base classes. It doesn't do exactly what I want but everything behaves like normal. Constructors are called once (in ascending order), each function is called followed by the destructor.
My confusion here is actually two fold. If you un-comment the inheritance in the Main class, the code compiles, but new each ctor/dtor is called twice, first in ascending order order and then descending order. I've been unable to reason why this would occur, but it doesn't seem correct. Every explanation of inheritance I have ever seen is vague and doesn't explain why this would need to happen.
class Main //: public A, public B, public C
My second point of confusion is the protected members of the classes. I would think that if I un-comment the "protected:" keywords, proceeding the methods in the base classes, I should be able to call them from the inherited classes. As I understand it, I should even be able to inherit them as private, assuming I only want the children to have this functionality. Alas, I just get error messages about the method being protected.
I'm well aware that my understanding has some major shortfalls, but I've been exhaustively searching for an explanation with no luck. I could really use some constructive insight in to what is going on here,
Thanks,
#include <iostream>
#include <memory>
using namespace std;
class A
{
public:
A() { cout << "Ctor A\n";}
~A() { cout << "Dtor A\n";}
//protected:
void func() { cout << "Function A\n"; }
};
class B
{
public:
B() { cout << "Ctor B\n";}
~B() { cout << "Dtor B\n";}
//protected:
void func() { cout << "Function B\n"; }
};
class C
{
public:
C() { cout << "Ctor C\n";}
~C() { cout << "Dtor C\n";}
//protected:
void func() { cout << "Function C\n"; }
};
class Main //: public A, public B, public C
{
public:
Main(A *a, B *b, C *c);
private:
std::unique_ptr<A> mA;
std::unique_ptr<B> mB;
std::unique_ptr<C> mC;
};
Main::Main(A *a, B *b, C *c) : mA(a), mB(b), mC(c)
{
mA->func();
mB->func();
mC->func();
}
int main()
{
Main m(new A, new B, new C);
return 0;
}
In case anyone is curious, I've been trying to compile this on ideone.com with the gcc v8.3 compiler.
If you un-comment the inheritance in the Main class, the code compiles, but new each ctor/dtor is called twice, first in ascending order order and then descending order. I've been unable to reason why this would occur, but it doesn't seem correct. Every explanation of inheritance I have ever seen is vague and doesn't explain why this would need to happen.
You have three calls to new. Then you construct a Main, which requires constructing an A, a B, and a C. Since an instance of a Main is an A, a B, and a C, those three constructors have to be called to construct valid instances of those three types.
I would think that if I un-comment the "protected:" keywords, proceeding the methods in the base classes, I should be able to call them from the inherited classes.
Sure, but not on an arbitrary instance of the class that isn't even of the derived type! You have:
mA->func();
This is in a member function of class Main, but is operating on something that isn't an instance of class Main. The class Main has special access to itself as an instance of class A -- its internal interface can use protected functions of itself as an instance of class A, but that's it.
This question already has answers here:
No Matching Function Call to Base class
(4 answers)
Closed 3 years ago.
Consider the following:
# include <iostream>
using namespace std;
class Base{
public:
Base(int a) {
cout << "Base" << endl;
}
};
class Child: public Base{
public:
Child(int a) {
cout << "Child" << endl;
}
};
int main() {
Child c = Child(0);
}
On compilation the error no matching function for call to ‘Base::Base()’ is given. Explicitly declaring a default constructor for Base fixes this issue.
It seems to me that if I want to inherit from a class, then it needs to have a default constructor? Even though (in this example) it never gets called? Is this correct, and if so, why? Otherwise, what's wrong the above code?
No, that is not a correct assumption.
You just have an error. Your derived class constructor must call the one and only Base constructor you provide which is a one parameter constructor.
Child(int a)
: Base(a)
{
cout << "Child" << endl;
}
I'm learning about multiple inheritance and the diamond problem, and when I make a function call from the most derived class Visual Studio tells me that the call is ambiguous:
struct A
{
virtual void aFunction() { cout << "I am A\n"; }
};
struct B : A {};
struct C : A {};
struct D : B, C {};
int main()
{
D DObj;
DObj.aFunction(); // This is an ambiguous call
}
I understand if I had overridden the base class function in the B and C classes then the call would be ambiguous, but isn't "aFunction()" the same in B and C?
Also, making B and C inherit from A virtually makes the error go away. But my understanding of the keyword "virtual" when inheriting, ie., (Derived : virtual Base), is that it prevents a "more derived class" further down the chain from inheriting multiple copies of a Base up the chain. In inheritance multiple copies of member variables can be inherited, but only one copy of a function with the same name. So for example I could have 5 Derived classes each deriving from Base, and then a MostDerivedClass inheriting from all the 5 Derived classes, in the MostDerivedClass I would have 5 copies of the Base class "member variables", but only one copy of a function with the same name.
So in other words the "virtual" keyword for inheritance should prevent multiple Base "member variable" copies. I don't understand why it would clear up an ambiguous function call in this case.
EDIT: Thank you, it's slowly sinking in. It was impossible for me to imagine "two copies" of A in D, because A is empty (no size). But then I remembered that C++ never creates empty classes, on my setup for example an empty class has size 1. Then I was able to imagine "two copies" of A in D, and it's starting to make sense now.
The call is ambiguous because there are two possible A base objects that could be passed as the this argument of the call. Even though it is the same physical function that ulitimately get called, and that function completely ignores its this argument, the fact that there are two of them makes it ambiguous.
Using virtual inheritance means that there would be only one A base object, so then the call would not be ambiguous.
Because multiple copies of member variables are inherited, you could have two separate copies of a function with different behavior.
struct A
{
int x;
virtual void aFunction() { cout << "I am A with value " << x ; }
};
struct B : A {
};
struct C : A {
};
struct D : B, C {};
int main()
{
D DObj;
((B*)(&DObj))->x = 0; // set the x in B to 0
((C*)(&DObj))->x = 1; // set the x in C to 1
DObj.aFunction(); // This is an ambiguous call
}
Should this output 0 or 1?
The compiler could detect the specific case of an inline function that does not reference this, but you can easily work around the issue so its not worth the complexity for a relatively rare case.
use the virtual inheritance to solve the diamond prolem:
struct A
{
int x;
virtual void aFunction() { cout << "I am A with value " << x ; }
};
struct B : virtual A { // add virtual
};
struct C : virtual A { // virtual
};
struct D : B, C {};
Suppose i have this code:
#include <iostream>
using namespace std;
class A
{
protected:
virtual ~A() { cout << "A destructor reached." << endl;}
friend class Z;
};
class B : public A
{
protected:
virtual ~B() { cout << "B destructor reached." << endl; }
};
class Z
{
public:
void Test();
friend class A;
};
void Z::Test()
{
A* derived = (A*) new B();
delete derived;
}
int main()
{
Z test;
test.Test();
}
What is going to happen, will the B destructor be called? Is it legal? And if it's not, is there any way to call the derived constructor without making every class derived from A friend of Z?
The Standard, §11.5/1 "access to virtual functions," says
The access rules (Clause 11) for a virtual function are determined by its declaration and are not affected by the rules for a function that later overrides it.
So you can call B::~B as long as you have access to A::~A. But you must call it through A because Z does not have access to B.
By the way, the friend declaration in Z is useless since nothing is private or protected in it.
There are at least two questions involved here.
Yes, B's destructor will be called. That's how polymorphism works, that's how virtual destructors work, it's by design and it's a good thing.
The fact that a member function that is protected (or even private) in B but virtual and available (e.g. public) in A can be invoked via A* may seem a little odd at first, but it's by design too. What's the alternative? The only other option I can see would be to forbid inheritance that increases the restriction of a virtual member function; what good purpose would that serve?
If you don't want a method to be accessible, don't derive it from an accessible virtual parent method.
Feel free to edit the title I'm not sure how to phrase this.
I'm trying to figure out how to call a class's constructor other than the default when it is instantiated in another class. What I mean is this...
class A
{
public:
A(){cout << "i get this default constructor when I create a B" << endl;}
A(int i){cout << "this is the constructor i want when I create a B" << endl;}
};
class B
{
A a;
};
int main()
{
B *ptr = new B;
return 0;
}
I've done some searching but I don't see a way to do what I want. I thought maybe in B's declaration I could do A a(5) but that doesn't work.
Thanks
You can do that with a constructor initialization list (you might also want to look at this question and others similar to it).
This means that you will have to manually write a constructor for B:
class B
{
A a;
public: B() : a(5) {}
};
See it in action.