C++ copy constructor in inheritance - c++

#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):A(obj){cout<<"4";}
};
class C: virtual A
{
public:
C(){cout<<"5";}
C(const C & obj):A(obj){cout <<"6";}
};
class D:B,C
{
public:
D(){cout<<"7";}
D(const D & obj):C(obj),B(obj){cout <<"8";}
};
int main()
{
D d1;
D d(d1);
}
I am getting 13571468 as output. But I think that output should be 13572468. Why normal constructor is running instead on of copy constructor of class A?

Your code makes a copy of an instance of D, invoking its copy constructor.
Your class D's copy constructor only invokes the copy constructors of its C and B's superclasses. Because it does not invoke A's copy constructor, it gets default-constructed.
Virtually-inherited classes can be thought of as direct superclasses of the most-derived class. That's what virtual inheritance means. As such, in your instance of D, its virtually-inherited A is a direct superclass of D, and not of B or C; as such, B and C's invocations of A copy-constructor is not invoked.
When you have a virtually-inherited class, all your constructors really have two versions created "behind the scenes": one that's responsible for constructing any virtually-inherited classes, and one that's not. The one that's not does not call the virtually-inherited classes's constructors.

Related

constructors inherited in c++

Excerpt from here:
Constructors are different from other class methods in that they create new objects, whereas other methods are invoked by existing objects. This is one reason constructors aren’t inherited. Inheritance means a derived object can use a base-class method, but, in the case of constructors, the object doesn’t exist until after the constructor has done its work.
Does a constructor create new object or when a object is called the
constructor is called immediately?
It is said that a constructor and destructor is not inherited
from the base class to the derived class but is the program below a
contradiction, we are creating an object of the derived class but it
outputs constructor and destructor of the base class also?
class A{
public:
A(){
cout<< Const A called<<endl;
}
~A(){
cout<< Dest A called <<endl;
}
};
Class B : public A{
public:
B(){
cout<< Const B called <<endl;
}
~B(){
cout<< Dest B called <<endl;
}
};
int main(){
B obj;
return 0;
}
Output:
Const A called
Const B called
Dest B called
Dest A called
A derived class D does not inherit a constructor from B in the sense that, specifying no explicit D constructors I can use my B(int) like to construct a new D(1);.
However, what I can do is use a base class constructor in the definition of a derived class constructor, like D::D(void) : B(1) {}.
Less abstract, suppose I have a constructor for Person that takes a gender parameter, I might wish to create a:
class Son: Person{
public:
Son(void) : Person(male) {};
};
to construct a Son, which is obviously a Person, but certainly doesn't need parameterised gender.
Destructors are 'inherited' in the sense that on the closing brace of D::~D(){} a call to ~B() is implied.

Prohibiting definition of a copy constructor in an inherited class

I want to make an abstract base class non-copyable and force any classes that derive from it to be non-copyable. The below code uses Boost's noncopyable as defined in noncopyable.hpp yet still allows D, the derived class, to define a copy constructor.
class noncopyable
{
protected:
noncopyable() {}
~noncopyable() {}
private: // emphasize the following members are private
noncopyable( const noncopyable& );
const noncopyable& operator=( const noncopyable& );
};
class D : noncopyable
{
public:
D() { }
D(const D&) { }
};
int main()
{
D a;
D b(a);
return 0;
}
This code compiles and runs (http://ideone.com/g4gGLm), when I expected it to throw a compile-time error about D's copy constructor. Maybe I have misinterpreted what this noncopyable class is meant to do. If so, is there any way to force derived classes to not define a copy constructor? (Answer can use C++11, but preferably not boost)
The reason this works is because D(const D&) calls the default constructor of the base class, not the copy constructor. (counter-intuitive at first, but it makes sense considering all constructors behave like this)
Since the copy constructor isn't called, a copy of the base object isn't created unless you explicitly ask for one:
D(const D& d) : noncopyable(d) { }
which would indeed result in an error. So in fact, your issue is a non-issue - there's no copying of noncopyable going on.
I'm not aware of any straight-forward way to force a derived class do disallow copying, nor would I recommend using one if there was.
You need to delete the copy constructor of D. Right now you allow copy-construction of D's by not trying to copy-construct the base class. The following variants will not compile:
class E: noncopyable
{
};
E e, e2(e);
class F: noncopyable
{
public:
F(const F &init): noncopyable(init)
{}
};

How is this initialization list implemented using a virtual class?

#include<iostream.h>
class A{
public:
int i;
A(int j=3):i(j){}
};
class B:virtual public A{
public:
B(int j=2):A(j){}
};
class C:virtual public A{
public:
C(int j=1):A(j){}
};
class D:public B, public C {
public:
D(int j=0):A(j), B(j+1), C(j+2){}
};
int main()
{
D d;
cout<<d.i;
return 0;
}
I am not being able to understand how the final output is zero. Every time j is initialized in default way to some fixed value, how is the value initialized in the constructor of class D being passed to class A?
Since A is a virtual base class, it should be constructed only once, so it is not possible to create it with different constructor parameters, and the C++ compiler has to choose one way of creating a base class.
The obvious question is: which one is used?
And the rule is: the one specified in the most derived class that inherits A directly.
The initialization order is simple: first A (with the parameter value from D constructor initialization list), then B (it is D's first ancestor; and it uses the instance of A created before), then C (and it shares the same A instance), finally D (and it also shares the same A object as B and C).
The rule with virtual base inheritance is:
"The most derived class in a hierarchy must construct a virtual base"
In your case, from the most derived class D You explicitly called the constructor of A by passing an argument 0 So it sets the i to 0. As mentioned in rule virtual base class is constructed through most derived class only and the other constructor calls through intermediate hierarchy have no effect since it is only constructed once.
The order of calling is:
A(int)
B(int)
C(int)
Good Read:
Why virtual base class constructors called first?

how to force base class constructors to be called in derived classes?

basic c++ question i'm fairly sure. if i have a base class with a constructor that takes no parameters, and just initializes some of the protected members, does a derived class instantly call this base constructor too if it matches the parameters (wishful but unlikely thinking), and if not, is there a way to force it to automatically call said base constructor from the derived class WITHOUT having to explicitly tell it to do so in the derived class? I ask because i'm writing a wrapper of sorts and there are some protected members that i want initialized to specific values initially, and then i want to derive and manipulate this base class to my needs, but i wouldn't like an outside user to have to remember to explicitly call the base constructor or set these values within their own constructor.
Yes, the default base constructor is always called unless explicitly stated otherwise.
For example:
class A
{
public:
A() { std::cout << "A"; }
};
class B : A
{
public:
B() {}
};
int main()
{
B b;
return 0;
}
will output:
A
By "explicitly stated otherwise" I mean that you can call a different constructor from the derived class:
class A
{
public:
A() { std::cout << "A"; }
A(int) { std::cout << "AAA"; }
};
class B : A
{
public:
B() : A(1) {} //call A(int)
};
int main()
{
B b;
return 0;
}
will output
AAA
Important if you don't have a default constructor (you declare a non-default constructor and not a default one) or the default constructor is not visible (marked as private), you need to explicitly call an available constructor in the derived class.
If your base-class has a "default constructor" (a constructor that takes no parameters; either explicitly provided by you, or implicitly provided by the compiler because you didn't explicitly provide any constructors), then every derived-class constructor will automatically call that unless you specify that they call a different constructor instead.
(If your base-class doesn't have a "default constructor", because you've provided one or more constructors that take parameters and no constructor that doesn't, then it's a compile-error for a derived-class constructor not to indicate the base-class constructor it calls.)

Understanding virtual base classes and constructor calls

I'm a bit confused about how virtual base classes work. In particular, I was wondering how the constructor of the base class gets called. I wrote an example to understand it:
#include <cstdio>
#include <string>
using std::string;
struct A{
string s;
A() {}
A(string t): s(t) {}
};
struct B: virtual public A{
B(): A("B"){}
};
struct C: virtual public A {};
struct D: public B, public C {};
struct E: public C, public B {};
struct F: public B {};
int main(){
D d;
printf("\"%s\"\n",d.s.c_str());
E e;
printf("\"%s\"\n",e.s.c_str());
F f;
printf("\"%s\"\n",f.s.c_str());
B b;
printf("\"%s\"\n",b.s.c_str());
}
Which outputs
""
""
""
"B"
I wasn't sure what would happen in the first two cases, but for the third one at least I was expecting the output to be "B". So now I'm just confused. What are the rules for understanding how the constructor of A gets called?
There is always just one constructor call, and always of the actual, concrete class that you instantiate. It is your responsibility to endow each derived class with a constructor which calls the base classes' constructors if and as necessary, as you did in B's constructor.
Update: Sorry for missing your main point! Thanks to ildjarn.
However, your B inherits virtually from A. According to the standard (10.1.4 in the FIDS), "for each distinct baseclass that is specified virtual, the most derived object shall contain a single base class subobject of that type". In your case this means that when constructing the base, your class F immediately calls A's default constructor, not B's.
Virtual base classes are always constructed by the most derived class.