I just want to understand the flow how it happens as am new to c++.
Let me elaborate my problem statement.
class test1 {
public:
test1() {
cout << " test1::constructor called" << endl;
}
~test1() {
cout << " test1::destrcutor called" << endl;
}
};
class test2 {
public:
test2() {
cout << " test2::constructor called" << endl;
}
~test2() {
cout << " test2::destrcutor called" << endl;
}
};
class derived :public test1, public test2 {
test2 t2;
test1 t1;
public:
derived() {
cout << " derived constructor called" << endl;
}
~derived() {
cout << "derived destructor called" << endl;
}
};
int main() {
derived d;
return 0;
}
The output of the above program shows
test1::constructor called
test2::constructor called
test2::constructor called
test1::constructor called
derived constructor called
derived destructor called
test1::destrcutor called
test2::destrcutor called
test2::destrcutor called
test1::destrcutor called
So here my question is at what points it called the constructor of the member variables in derived class as I have not put any initializer for the same.
The order of construction is bases, then members so :-
test1::constructor called << first base of 'derived'
test2::constructor called << second base of 'derived'
test2::constructor called << member of 'derived' t2
test1::constructor called << member of 'derived' t1
derived constructor called << code in 'derived::derived'
derived destructor called << code in 'derived::~derived'
test1::destrcutor called << destruction of t1
test2::destrcutor called << destruction of t2
test2::destrcutor called << destruction of derived
test1::destrcutor called << destruction of derived
There is only one destructor of an object, and it has a defined order to destroy objects. That is destroy all the members from bottom to top of the class.
Then destroy the class, and its bases in "reverse order".
Each constructor can choose what to initialize, but not the order.
a_class::a_class( params ) :
base_n( params ), base_n_1( params ),
member_1( params), member_2( params),...
This member initialization list allows different parameters to be given to construct all the bases and objects, but does not effect the order. It is always first_base, second_base, first_member, second_member, ...
This ordering is to ensure it is the opposite of the destructor.
These rules allowed me to work out which message was from the members, and which from the bases.
A member which does not get initialized from the member initialization list will still get its default constructor called test2::test2. As once a class/struct have a constructor, they will only come into existence by having a constructor called.
Plain-old-Data or POD are simple types such as int which don't have constructors. They are left uninitialized (whatever values were left behind in the memory).
Related
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;
}
```
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).
I understand that you can't expect to have a derived reference pointing at its base class because it will lose functionality, but I was curious on what would actually happen to understand more about the sequence of events.
#include <iostream>
struct Base
{
Base() { std::cout << "Base constructor" << std::endl; }
Base(const Base&) { std::cout << "Base copy constructor" << std::endl; }
~Base() { std::cout << "Base destructor" << std::endl; }
};
struct Derived : public Base
{
Derived(const Base& b) : Base(b) { std::cout << "Derived constructor" << std::endl; }
~Derived() { std::cout << "Derived destructor" << std::endl; }
};
struct OwnsDerived
{
OwnsDerived(const Derived& derivedObject) : derivedRef(derivedObject) { std::cout << "OwnsDerived created..." << std::endl; }
const Derived& derivedRef;
};
int main () {
std::cout << "Main starts: " << std::endl;
const Base b;
std::cout << "\nMain creating object that owns a reference to derived: " << std::endl;
OwnsDerived s(b);
std::cout << "\nMain ends: " << std::endl;
return 0;
}
The result I got was:
Main starts:
Base constructor
Main creating object that owns a reference to derived:
Base copy constructor
Derived constructor <-- why is a derived trying to be created when passing the wrong type in the constructor
OwnsDerived created...
Derived destructor //<-- these are treated as temporaries
Base destructor //<--
Main ends:
Base destructor
Even when I change the reference to be a copy of the object instead, it behaves similarly, which is also surprising to me.
I would really appreciate any pointers or any resources to learn about the more nuanced mechanics of these constructor/destructors!
OwnsDerived constructor takes a Derived by reference to const, but you pass a Base instance. So, the compiler will try to convert the Base instance to a Derived. That's possible by calling the (implicit) conversion constructor in Derived. So, a temporary instance of Derived is created.
To fix the implicit conversion, declare the Derived constructor as explicit.
struct Derived : public Base
{
explicit Derived(const Base& b);
//...
};
Reference to this https://www.tutorialspoint.com/cplusplus/cpp_functions.htm
In CPP when ever you call a function, it will copy the paramenter of that function instead of using it directly
So, when you call the contructor of OwnsDerived it use const Base b as it paramenter. The system will copy this to other memory where you get this log Base copy constructor. I will call this a copied_b. So copied_b is Base it will convert it to Derive as the contructor of OwnsDerived required a Derive so there is Derived constructor. I call this derived_of_copied_b. At the end of the contructor of OwnsDerived both copied_b and derived_of_copied_b will be destroy, where you will see Derived destructor and Base destructor right after OwnsDerived created....
I wish this could explain your question.
In this program "A's constructor called " is printing 2 times. My doubt is why "A's constructor called " is not printing with
A b = B::getA();
while getting printed with
A a;
In both the cases we are creating a new object.
Here is my Program:
#include <iostream>
using namespace std;
class A
{
public:
A() { cout << "A's constructor called " << endl; }
};
class B
{
static A a;
public:
B() { cout << "B's constructor called " << endl; }
static A getA() { return a; }
};
A B::a; // definition of a
int main()
{
A a;
A b = B::getA();
return 0;
}
The first constructor is called at program startup, when the static A within B is created.
The second constructor is called within your main when A is allocated on the stack.
There are no more calls to the default A constructor. When you call getA() a copy constructor will be used, which as you have not defined, will be provided by the compiler.
Because getA() calls a copy constructor, which you haven't written, so the default one will be called.
A b = B::getA();
That initialises b using the copy constructor. You're only tracing the default constructor, which isn't used here. If you wanted to trace the copy constructor too, then you'd need to provide one:
A(A const &) { cout << "A's copy constructor called " << endl; }
one contructore is getting called with "static A a" and "A B::a" i.e static initialization of a which is member of class B
during the execution of program in C, C++ all global and static variables initialized first.
#include <iostream>
class A
{
public:
A() { std::cout << " A ctor" << std::endl; }
A(int i) { std::cout << " A ctor i" << std::endl; }
~A() { std::cout << " A dtor" << std::endl; }
};
class B: public A
{
public:
B() : A () { std::cout << " B ctor" << std::endl; }
~B() { std::cout << " B dtor" << std::endl; }
};
class C: public A
{
public:
B _b;
C() : _b (), A () { std::cout << " C ctor" << std::endl; }
~C() { std::cout << " C dtor" << std::endl; }
};
int main ()
{
C c;
}
The output is:
A ctor
A ctor
B ctor
C ctor
C dtor
B dtor
A dtor
A dtor
What is the order of the init. list? Why, in the init. list of C, ctor of A called before ctor of B? I thought the output should be:
A ctor
B ctor
A ctor
C ctor
C dtor
A dtor
B dtor
A dtor
Thanks.
The order in which you write initializations in the initialization list is not important, the order of initialization is determined independently of that list by other rules:
First the base class is initialized. That's why in the construction of C the base class constructor A is called first. Everything that belongs to the base class is constructed in this step (base classes and member variables belonging to the base class), just like when a normal object of that base class would be constructed.
Then the member variables of the derived class are initialized, in the order in which they are declared in the class. So if there are several member variables, the order in which they are declared determines the order in which they are initialized. The order of an initialization list is not important.
Base class constructors are called before derived class constructors. This allows the derived class to use members in the base class during their construction.
During destruction, the opposite is true. Subclass destruction occurs before the base class, for exactly the same reason.
If you think about it - it makes perfect sense. The base class has no knowledge of the subclass, but the opposite is not true. This determines the ordering in order for everything to work as expected.
I think your confusion is why is C's initialization list processed right to left instead of left to write. It is because, the compiler processes parameters in "last in first out" fashion. Hence the order: First A's c'tor. Since _b is an object of B which is derived from A, base class is constructed before the derived class so A c'tor is called and then B's c'tor. And finally, C's c'tor is called. When C's object is destructed, it follows the reverse order.
If you use GNU compiler, -Wall option will help you.