Consider the below code:
#include<iostream>
using namespace std;
class A
{
public:
A() {cout << "1";}
A(const A &obj) {cout << "2";}
};
class B: virtual A
{
public:
B() {cout << "3";}
B(const B & obj) {cout<< "4";}
};
class C: virtual A
{
public:
C() {cout << "5";}
C(const C & obj) {cout << "6";}
};
class D:B,C
{
public:
D() {cout << "7";}
D(const D & obj) {cout << "8";}
};
int main()
{
D d1;
cout << "\n";
D d(d1);
}
The output of the program is below:
1357
1358
So, for line D d(d1)
the copy constructor of D
class is bein called. During inheritance we need to explicitly call copy constructor of base class otherwise only default constructor of base class is called. I understood till here.
My Problem:
Now I want to call copy constructor of all base classes during D d(d1)
execution. For that if I try below
D(const D & obj) : A(obj), B(obj), C(obj) {cout << "8";}
Then I get this error:
error: 'class A A::A' is inaccessible within this context
How to resolve the issue. I want copy constructor of A
, B
and C
when copy constructor of D
gets called. It might be very small change but I am not getting.
Alternative solution which doesn't require changing the inheritance modifiers of class
B
orC
:The way you have inherited your classes, all of them use
private
inheritance.By changing the inheritance of
B
fromA
andC
fromA
to beprotected
orpublic
, you can resolve the problem.or
and then update
D
's copy constructor to:PS It's baffling to me that the default constructor works even with
private
inheritance.Regarding access checking for constructors: from [class.access]/6
similarly, [class.access]/4
Regarding base class subobject initialization: from [class.base.init]/9
The lack of any ctor-initializer for a base class subobject means that the subobject is default-initialized; from [dcl.init]/7
So the lack of any base in a ctor-initializer is a request for default-initialization for that base, which means calling the default constructor.
The lack of mention of a base class makes no difference; in any case, a constructor has no name and is not named in the ctor-initializer, it is referenced either explicitly or implicitly. There is nothing in the standard suggesting that access control should not be performed in such case.
It seems like the constructor, being from an inaccessible base class, cannot be called either way, so your program should not compile.
In any case, you can change the inheritance from private to protected, even add a path to the virtual base class:
This way, the virtual base class
A
is still private, but is accessible toD
.First, lets change your inheritance as currently it is private:
Now, in your copy constructor, explicitly specify that the copy constructors of
A
andB
andC
should be called:And the output will be as desired (
2468
).Why?
When we have virtual base classes, they must be initialized by the most derived class, otherwise there would be ambiguity concerning whether
B
orC
for example is responsible for the construction ofA
.In particular, if you define a copy constructor, and omit the list of copy constructors it should call, then the default constructors will be used.