Calling undefined copy constructor - c++

This is my class hierarchy.
#include<iostream>
using namespace std;
class baseClass
{
public:
int var;
int* varPtr;
baseClass(int value) : var(value), varPtr(&var)
{
cout << "baseClass constructor" << endl;
}
};
class derivedClass : public baseClass
{
public:
derivedClass(int value) : baseClass(value)
{
cout << "derivedClass constructor" << endl;
}
derivedClass(const derivedClass& objToCopy)
{
cout << "derivedClass copy constructor" << endl;
}
};
int main(int argc, char** argv)
{
derivedClass derivedObj1(5);
derivedClass derivedObj2(derivedObj1);
return 0;
}
This code gives me a no default constructor error. Which is correct as I don't have a default constructor defined. Now my question is when I call the copy constructor of baseClass from derivedClass.
#include<iostream>
using namespace std;
class baseClass
{
public:
int var;
int* varPtr;
baseClass(int value) : var(value), varPtr(&var)
{
cout << "baseClass constructor" << endl;
}
};
class derivedClass : public baseClass
{
public:
derivedClass(int value) : baseClass(value)
{
cout << "derivedClass constructor" << endl;
}
derivedClass(const derivedClass& objToCopy) : baseClass(objToCopy) // <- ADDED
{
cout << "derivedClass copy constructor" << endl;
}
};
int main(int argc, char** argv)
{
derivedClass derivedObj1(5);
derivedClass derivedObj2(derivedObj1);
return 0;
}
Now I get no error although I have not defined a copy constructor. There is no constructor that takes a reference of baseClass. Why isn't the compiler not complaining? Why is it happy to just do bitwise copy when I'm explicitly calling for the copy constructor? Why there is no error saying that baseClass(const baseClass&) undefined?
Thank you.

Copy-constructors are implicitly added to the class if you do not provide one. In order to prevent copying of your class, you can delete the compiler-generated one, like so:
baseClass(const baseClass& objToCopy) =delete;
The compiler errors in the first program because it attempts to call a no-argument constructor instead of a copy constructor to construct the base-class part of the object. Since you have already defined a custom constructor for the class, the default no-argument version is not implicitly generated.

In derived class the copy constructor is defined that way :
derivedClass(const derivedClass& objToCopy)
{
cout << "derivedClass copy constructor" << endl;
}
By default, the copy constructor of a derived class uses the copy constructor of base class but you were explicitely declaring a copy constructor without specifying how you wanted to construct the base class object, so the compiler tried to use the default constructor.
You should write :
derivedClass(const derivedClass& objToCopy): baseClass(objToCopy.value)
{
cout << "derivedClass copy constructor" << endl;
}
to correctly use the explicit base constructor.

I believe, the reason for this behavior has to do with constructor delegation since C++11.

Related

How do we call Base class Constructor from Derived Class using delegating Constructors

I know and I have read many threads to call a base class constructor from a Derived class, But I wanted to implement it using Delegating constructors
Here is my code
The error states
"A delegating constructor cannot have other mem-initializers"
#include <iostream>
using namespace std;
// Shivang101
class Base
{
private:
int value;
public:
Base() : value{0}
{
cout << "Base no args constructor called" << endl;
}
Base(int x) : value{x}
{
cout << "Base (int) overloaded constructor called" << endl;
}
~Base()
{
cout << "Base Destructor called" << endl;
}
};
class Derived : public Base
{
private:
int testing_value;
int doubled_value;
// using Base ::Base;
public:
Derived() : Derived{0, 0}
{
cout << "NO arg constructor called" << endl;
};
// In the below line I'm Trying a call the base class constructor but getting error
Derived(int testing_val) : Base{testing_val}, Derived{testing_val, 0}
{
cout << "One arg constructor called" << endl;
}
Derived(int testing_val, int doubled_val) : testing_value{testing_val}, doubled_value{doubled_val}
{
cout << "Delegating constructor/ overloaded called" << endl;
}
~Derived()
{
cout << "Derived destructor called" << endl;
}
};
int main()
{
Derived d{1000};
return 0;
}
I wanted to call my base class constructor and initialize the "value" in Base class as "1000" and initialize the "testing_*value" and "doubled_*value" in the Derived class as "1000" and "2000" respectively
A constructor is responsible for initializing all members and base subobjects.
A delegating constructor delegates to a different constructor.
It cannot be both. Either you delegate elsewhere or you initialize members and base subobjects.
Quoting from cppreference:
Delegating constructor
If the name of the class itself appears as class-or-identifier in the
member initializer list, then the list must consist of that one member
initializer only; such a constructor is known as the delegating
constructor, and the constructor selected by the only member of the
initializer list is the target constructor
I suppose you can rearrange the constructors to achieve desired effect. Though I don't see how it can be done without implementing one more constructor or change the way of delegating, because currently the one taking two arguments calls the default constructor of Base, but the one delegating to it attempts to call Base{testing_val}.
I Found the solution to my Question
We can call the Base Class Constructor from Derived Class using Delegating constructor by calling the Base class constructor in the delegating constructor itself
In the I was passing Base Class constructor call from overload to delegating constructor
No I have called Base Class Constructor from the Delegating constructor itself
#include <bits/stdc++.h>
using namespace std;
// Shivang101
class Base
{
private:
public:
int value;
int value2;
Base() : value{0}
{
cout << "Base no args constructor called" << endl;
}
Base(int x) : value{x}
{
cout << "Base (int) overloaded constructor called" << endl;
}
~Base()
{
cout << "Base Destructor called" << endl;
}
};
class Derived : public Base
{
private:
public:
int testing_value;
int doubled_value;
// using Base ::Base;
Derived() : Derived{0, 0}
{
cout << "NO arg constructor called" << endl;
};
Derived(int testing_val) : Derived{testing_val, 0}
{
cout << "One arg constructor called" << endl;
}
Derived(int testing_val, int doubled_val) : Base{testing_val}, testing_value{testing_val}, doubled_value{doubled_val * 2}
{
cout << "Delegating constructor/ overloaded called" << endl;
}
~Derived()
{
cout << "Derived destructor called" << endl;
}
};
int main()
{
Derived d{1000};
cout << d.value << endl;
return 0;
}
```

Which base class constructors do I need to put in initializer lists? [duplicate]

I don't understand why in the following code, when I instanciate an object of type daughter, the default grandmother() constructor is called ?
I thought that either the grandmother(int) constructor should be called (to follow the specification of my mother class constructor), or this code shouldn't compile at all because of the virtual inheritance.
Here compiler silently calls grandmother default constructor in my back, whereas I never asked for it.
#include <iostream>
class grandmother {
public:
grandmother() {
std::cout << "grandmother (default)" << std::endl;
}
grandmother(int attr) {
std::cout << "grandmother: " << attr << std::endl;
}
};
class mother: virtual public grandmother {
public:
mother(int attr) : grandmother(attr) {
std::cout << "mother: " << attr << std::endl;
}
};
class daughter: virtual public mother {
public:
daughter(int attr) : mother(attr) {
std::cout << "daughter: " << attr << std::endl;
}
};
int main() {
daughter x(0);
}
When using virtual inheritance, the virtual base class's constructor is called directly by the most derived class's constructor. In this case, the daughter constructor directly calls the grandmother constructor.
Since you didn't explicitly call grandmother constructor in the initialization list, the default constructor will be called. To call the correct constructor, change it to:
daugther(int attr) : grandmother(attr), mother(attr) { ... }
See also This FAQ entry.

confusion in constructor calling in virtual function

Confusion in constructor calling via temporary object as argument in a function
#include <iostream>
using namespace std;
class Base
{
protected:
int i;
public:
Base() {
cout<<"\n Default constructor of Base \n";
}
Base(int a)
{
i = a;
cout<<"Base constructor \n";
}
void display(){
cout << "\nI am Base class object, i = " << i ;
}
~Base(){
cout<<"\nDestructor of Base\n";
}
};
class Derived : public Base
{
int j;
public:
Derived(int a, int b) : Base(a) {
j = b;
cout<<"Derived constructor\n";
}
void display() {
cout << "\nI am Derived class object, i = "<< i << ", j = " << j;
}
~Derived(){
cout<<"\nDestructor Of Derived \n";
}
};
void somefunc (Base obj) //Why there is no call to default constructor of Base class
{
obj.display();
}
int main()
{
Base b(33);
Derived d(45, 54);
somefunc( b) ;
somefunc(d); // Object Slicing, the member j of d is sliced off
return 0;
}
My question is that why there is no call to Default Constructor of Base Class,when we are creating a Temporary object of a Base class in function ( void somefunc(Base obj) )
My question is that why there is no call to Default Constructor of Base Class,when we are creating a Temporary object of a Base class in function
An instance of Base is constructed using the copy constructor when the call to somefunc is made. That object is not constructed using the default constructor. A default copy constructor is created by the compiler since you haven't defined one.
It's not a temporary object. The argument is passed by value to the function, so the copy ctor will be called, not default ctor. Note that compiler will provide a copy constructor if there is no user defined, you can define it by yourself to output some debug info.
Base(const Base& a) : i (a.i)
{
cout<<"Base copy constructor \n";
}
it will call copy construct function to create the Temporary object of a Base class in function

C++ default, copy and promotion constructor

I have the following code [This is an interview question]:
#include <iostream>
#include <vector>
using namespace std;
class A{
public:
A(){
cout << endl << "base default";
}
A(const A& a){
cout << endl << "base copy ctor";
}
A(int) {
cout << endl << "base promotion ctor";
}
};
class B : public A{
public:
B(){
cout << endl << "derived default";
}
B(const B& b){
cout << endl << "derived copy ctor";
}
B(int) {
cout << endl << "derived promotion ctor";
}
};
int main(){
vector<A> cont;
cont.push_back(A(1));
cont.push_back(B(1));
cont.push_back(A(2));
return 0;
}
The output is :
base promotion ctor
base copy ctor
base default
derived promotion ctor
base copy ctor
base copy ctor
base promotion ctor
base copy ctor
base copy ctor
base copy ctor
I am having trouble understanding this output, specifically why base default is called once and the last 3 copy ctor. Can someone please explain this output ?
Thanks.
The base default constructor is called once from the line
cont.push_back(B(1));
All your B constructors call the default A constructor. The last two copy constructors are because of a vector re-allocation. For example, if you added
cont.reserve(3);
before the push_backs, they'd go away.
The one before that is a copy of the temporary A(2) in your final push_back.

I'm receiving error when calling base copy constructor

Im receiving error C2082: redefinition of formal parameter 'rval' in this code while trying to call base copy ctor explicitly:
#include <iostream>
using namespace std;
class Base
{
public:
Base(const Base& rhs){ cout << "base copy ctor" << endl; }
};
class Derived : public Base
{
public:
Derived(const Derived& rval) { Base(rval) ; cout << "derived copy ctor" << endl; }
// error C2082: redefinition of formal parameter 'rval'
};
int main()
{
Derived a;
Derived y = a; // invoke copy ctor
cin.ignore();
return 0;
}
However if do it like this:
Derived(const Derived& rval) { Base::Base(rval) ; cout << "derived copy ctor" << endl; }
then is OK.
Why am I asking this?
according to the answers on StackOwerflow
I do not have to use operator :: to access base copy ctor,
so why do I receive this error?
btw: I'm using visual studio 2010.
I'm having one more question:
Do I have to call base's move constructor in user defined move constructor of derived class?
To call the base constructor you need to put the call in the member initalization list
class Derived : public Base
{
public:
Derived(const Derived& rval) : Base(rval)
{
cout << "derived copy ctor" << endl;
}
};
Assuming that you mean 'move' constructor is the copy constructor - Yes. You will have to call the Base's constructor. Otherwise the definition if the base object within the derived object will not be complete. You can either call a copy constructor or a normal constructor of the base class.