C++ default, copy and promotion constructor - c++

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.

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;
}
```

C++ subclass constructor is ignored

In the following code, when I initialize a subclass with an argument of the same class, the program calls the parent class constructor but not the subclass's [derived3]. However, if I pass in an argument belonging to just the parent class, it calls both functions correctly [derived2]. Why would the compiler ignore the subclass constructor in the former case?
#include <iostream>
class Base {
public:
Base() {
std::cout << "Base constructor" << std::endl;
}
Base(Base& b) {
std::cout << "Base parameterized constructor" << std::endl;
}
};
class Derived : public Base {
public:
Derived() {
std::cout << "Derived constructor" << std::endl;
}
Derived(Base& b) : Base(b) {
std::cout << "Derived parameterized constructor" << std::endl;
}
};
int main(int argc, char **argv) {
std::cout << "[base]" << std::endl;
Base base {};
std::cout << "[derived]" << std::endl;
Derived derived {};
std::cout << "[base2]" << std::endl;
Base base2 {base};
std::cout << "[derived2]" << std::endl;
Derived derived2 {base};
std::cout << "[base3]" << std::endl;
Base base3 {derived};
std::cout << "[derived3]" << std::endl;
Derived derived3 {derived};
}
Output:
[base]
Base constructor
[derived]
Base constructor
Derived constructor
[base2]
Base parameterized constructor
[derived2]
Base parameterized constructor
Derived parameterized constructor
[base3]
Base parameterized constructor
[derived3]
Base parameterized constructor
When you do
Derived derived3 {derived};
You are making a copy, so the copy constructor is called. Since you did not override the copy constructor with your own that prints a statement, you only see the base copy constructor get called.
Adding
Derived(Derived& d) : Base(d) {
std::cout << "Derived copy constructor" << std::endl;
}
will give you two print statements for the derived3 line.
That's because Base(Base& b) is not a regular parameterized constructor. It's a copy constructor.
This is a special type of constructor and is handled specially. derived3 calls both Derived copy constructor (implicitly declared by compiler) and Base copy constructor (declared by you).

Calling undefined copy constructor

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.

Explain this c++ code

#include <iostream>
using namespace std;
class A
{
int n;
public:
A()
{
cout << "Constructor called" << endl;
}
~A()
{
cout << "Destructor called" << endl;
}
};
int main()
{
A a; //Constructor called
A b = a; //Constructor not called
return 0;
}
output:
Constructor called
Destructor called
Destructor called
Constructor is called once while the destructor is called twice
What is happning here? Is this undefined behaviour?
The second line invokes what is called a Copy Constructor. Much like lawyers, if you do not have one, one will be provided for you by the compiler.
It is a special type of converter that is invoked when you initialize a variable with another of the same type.
A b(a)
A b = a
Both of these invoke it.
A(const A& a)
{
cout << "Copy Constructor called" << endl;
//manually copy one object to another
}
Add this code to see it. Wikipedia has more info.
In the snippet
A b = a
you are not calling your constructor, but the generated copy constructor:
class A
{
int n;
public:
A()
{
cout << "Constructor called" << endl;
}
A(const A& rv)
{
cout << "Copy constructor called" << endl;
// If you are not using default copy constructor, you need
// to copy fields by yourself.
this->n = rv.n;
}
~A()
{
cout << "Destructor called" << endl;
}
};
Default Copy Constructor is used to create the second instance.
When you leave the scope the destractor for both objects is called
There are two instances of object A created. One is created by a constructor, the other by the copy constructor. Since you did not explicitly define one, the compiler did the work for you.
Once the app exits, since there are two objects, the destructor method is called twice.
A b=a => A b(a) => This calls the default copy constructor of the class.

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.