here is a use of static class object inside another class along with a scope resoution operator now i'm not sure whether the static object or the scope resolution operator is the reason that the constuctor from a different class is also invoked.
the code is:
class A
{
public:
A()
{
cout<<"A's constructor"<<endl;
}
};
class B
{
static A a;
public:
B()
{
cout<<"B's constructor";
}
static A get()
{
return a;
}
};
A B :: a;
thus along with the main part
int main()
{
B b;
A a1=b.get();
A a2=b.get();
A a3=b.get();
}
And here is the output:
A's constructor
B's constructor
Another query is that whether the get function is actually doing anything?
Define one more constructor, the copy constructor, in the class A. For example
A( const A & ) { cout << "A's copy constructor" << endl; }
and you will get the following output
A's constructor
B's constructor
A's copy constructor
A's copy constructor
A's copy constructor
That is the first constructor is called to create the static object of the class A die to its definition
A B :: a;
Then within main there is created an object of the type B. And ion these statements
A a1=b.get();
A a2=b.get();
A a3=b.get();
there are created three object of the type A using the copy constructor.
Related
This question already has answers here:
Why does the implicit copy constructor calls the base class copy constructor and the defined copy constructor doesn't?
(3 answers)
Closed 11 months ago.
Consider the following example:
class A
{
public:
A()
{
cout<<"constructor A called: "<<this<<endl;
};
A(A const& other) = default;
};
class B : public A
{
public:
B()
{
cout<<"constructor B called: "<<this<<endl;
};
//This calls A's constructor
B(B const& other)
{
cout<<"B copy constructor called: "<<this<<endl;
};
//While this doesn't call A's constructor
//B(B const& other) = default;
};
int main()
{
B b;
B b2(b);
cout<<"b: "<<&b<<endl;
cout<<"b2: "<<&b2<<endl;
return 0;
}
Output:
constructor A called: 0x7fffc2fddda8
constructor B called: 0x7fffc2fddda8
constructor A called: 0x7fffc2fdddb0
B copy constructor called: 0x7fffc2fdddb0
b: 0x7fffc2fddda8
b2: 0x7fffc2fdddb0
Why is the constructor of A is called when copying B?
Shouldn't the copy constructor of A be called instead?
However, if you change class B's copy constructor to be default, the constructor of A is not called when copying which makes sense.
It will be nice if someone can give a reasonable explanation as to why.
Why is the constructor of A is called when copying B? Shouldn't the copy constructor of A be called instead?
No, it shouldn't.
A derived class must always initialize a base class. If the derived class has a constructor that is implemented explicitly by the user, but it does not explicitly call a base class constructor in its member initialization list, the compiler will make an implicit call to the base class's default constructor, regardless of the type of the derived constructor. The compiler does not make any assumption about the user's intent in implementing the derived constructor. If the user wants a specific base class constructor to be called, they need to make that call themselves.
Since B has an explicitly implemented copy constructor that lacks a member initialization list, the compiler initializes A by calling its default constructor, not its copy constructor.
IOW, this:
B(B const& other)
{
...
}
Is equivalent to this:
B(B const& other) : A()
{
...
}
NOT to this, as you are thinking:
B(B const& other) : A(other)
{
...
}
However, if you change class B's copy constructor to be default, the constructor of A is not called when copying which makes sense.
Correct, a default'ed copy constructor will call the base class's copy constructor, not its default constructor. The compiler is implicitly implementing the entire derived constructor, and so it will choose the appropriate base class constructor to call.
Lets say I have 2 diffrent classes.
Why when I put class A object as data member inside class B, the class that getting destroyed first is class B and then class A but when i put class A object in the builder of class B then class A getting destroyed first and then class B? for example:
class A {
public:
~A() { std::cout << "Deleting A\n"; }
};
class B {
private:
A object;
public:
~B() { std::cout << "Deleting B\n"; }
};
int main( void ) {
B test;
return 0;
}
result:
Deleting B
Deleting A
But the next example gives me the opposite result :
class A {
public:
~A() { std::cout << "Deleting A\n"; }
};
class B {
public:
B() { A object; }
~B() { std::cout << "Deleting B\n"; }
};
int main( void ) {
B test;
return 0;
}
result:
Deleting A
Deleting B
In your second example B test; calls the constructor of B.
The constructor B is just a function and it has a local variable A object;. This object is created and at the end of the scope (end of the constructor of B) it is detroyed.
Back in main at the end of main the object test is destroyed.
So in that case the object A object; is destroyed first, later object B test; is destroyed.
In your first example this is something different. There A object; is a member of class B, so the constructor of B is constructing the member automatically. The order of construction is: base classes first (not present in your example), then members, then the body of the constructor. Destruction is the opposite order: body of the destructor first, then the members (including your A object;), then the base classes (not present in your example).
As already said in a comment, you can easily step through the code in a debugger to get a better understanding of the order of execution.
Because the object of class A is destroyed as soon the constructor of class B finishes (because it is a local variable inside a function) and it is before the class B destructor be called.
In the second example you've got your object (instance of Class A), local in your Constructor. When you now instantiate B in your main function, the constructor is called, creates object, and destroys it, as sonn as the constructor has finished.
In your first example, object is a class member and lives as long as your class object in your main function. When the programm is finished it calls your costum Destructor, this is then executed first, then it destructs all members (standard Constructor).
Consider the following code
#include <iostream>
using namespace std;
class A
{
int x;
public:
A() { cout << "A's constructor called " << endl; }
};
class B
{
public:
static A a;
B() { cout << "B's constructor called " << endl; }
static A getA() { return a; }
};
A B::a; // definition of a
int main()
{
B b1, b2, b3;
A a = b1.getA();
cout<<&a<<endl;
cout<<&B::a;
return 0;
}
the output is
A's constructor called
B's constructor called
B's constructor called
B's constructor called
0x7fff03081280
0x601194
Now lets consider another similar code
#include <iostream>
using namespace std;
class A
{
int x;
public:
A() { cout << "A's constructor called " << endl; }
};
class B
{
public:
static A a;
B() { cout << "B's constructor called " << endl; }
static A getA() { return a; }
};
A B::a; // definition of a
int main()
{
B b1, b2, b3;
A a ;
a= b1.getA();
cout<<&a<<endl;
cout<<&B::a;
return 0;
}
the output is
A's constructor called
B's constructor called
B's constructor called
B's constructor called
A's constructor called
0x7ffc485a1070
0x601194
Now my question is that why in the first case the constructor of A is called only once , whereas in the second code its called twice.
Also the two output &a and &B::a are different so it means they are two different objects .
Please explain why this is so.
In your first code
A a = b1.getA();
the copy-constructor of A gets called which doesn't generate any output. Define it yourself and you'll get a similar output to your second code.
Hmm, B::a is B's (public) static member instance of otherwise quite an usual class A. So, the first A's constructor logged is that of B::a, which should be initialized before control enters main, but next you create a separate instance of A local to main, it is constructed in order alongside with other main's local variables (here, right after all the Bs) and it is naturally distinct from B::a.
Now my question is that why in the first case the constructor of A is called only once , whereas in the second code its called twice.
Because in the first case you default-initialised only the static B::a, and copy-initialised the local a.
In the second you default-initialised both objects.
The crucial difference is that you only print a message in the default constructor, and don't print anything in the copy constructor.
Also the two output &a and &B::a are different so it means they are two different objects .
That is correct. a is a local variable, while B::a is a static member variable. They are different objects.
Static member variables of class type represent a storage with process-wide life span. It gets initialized as such, at some point before entry point to program - the beginning of main() - is reached. That's the first constructor call.
The line
A a = b1.getA();
initializes object a by calling copy constructor and through return value optimization and copy elision there is no default constructor call.
The second variant:
A a; // A() call
a = b1.getA(); // operator= call
Modified class
class A
{
int x;
public:
A(const A& a): x(a.x) { cout << "A's copy constructor called " << endl; }
A(A&& a): x(a.x) { a.x = 0; cout << "A's move constructor called " << endl; }
const A& operator=(const A& a) { x = a.x; cout << "A's copy operator= called " << endl; }
A() { cout << "A's constructor called " << endl; }
};
would give this output in first case:
A's constructor called
B's constructor called
B's constructor called
B's constructor called
A's copy constructor called
And second case would result in:
A's constructor called
B's constructor called
B's constructor called
B's constructor called
A's constructor called
A's copy constructor called
A's copy operator= called
It is simple to understand that whenever the class instance (object) getting created associated constructor is getting called.
Now my question is that why in the first case the constructor of A is called only once , whereas in the second code its called twice.
You are creating second object directly in stack and constructor is getting called in later case, first one is the static and second one by creating object in stack by below statement.
A a ;
In first case, instead of constructor, copy constructor is getting called so thats why you are not getting the print statement second time.
A a = b1.getA();
I was trying the following program :
#include <iostream>
using namespace std;
class Type{
int i;
public:
Type() {cout << "type constructor "<<endl;}
Type (const Type &) { cout << "type copy constructor called" << endl;}
};
class MyClass {
Type variable;
public:
MyClass(Type a) {
cout << "inside MyClass constructor "<<endl;
variable = a;
}
};
void fun (Type){
return;
}
int main (){
Type t;
cout <<"t created"<<endl;
MyClass tmp = MyClass(t);
cout<<"calling fun"<<endl;
fun(t);
}
The output of this is :
type constructor
t created
type copy constructor called
type constructor
inside MyClass constructor
calling fun
type copy constructor called
I am wondering why default constructor is called when I pass it to MyClass constructor and why copy constructor is called when I pass it to fun()?
BTW same happens when I use initializer list.
I am wondering why default constructor is called when I pass it to MyClass constructor
It has nothing to do with passing argument here. As a member variable, variable will be default constructed at first.
class MyClass {
Type variable;
public:
MyClass(Type a) { // variable will be default constructed at first, since it's not initialized via member initializer list
cout << "inside MyClass constructor "<<endl;
variable = a; // then variable is assgined via assignment operator
}
};
You can specify how variable would be initialized by member intializer list, like
class MyClass {
Type variable;
public:
MyClass(Type a) : variable(a) { // variable will be direct initialized via copy constructor
cout << "inside MyClass constructor "<<endl;
// variable = a; // no need for assignment
}
};
The default constructor won't be called for this case.
Copy constructor is invoked for both the parameters (the one for MyClass constructor and the one for fun) and the logs you posted report that.
In fact, you have two times the following line:
type copy constructor called
Default constructor is invoked for data member variable, for it is not explicitly initialized.
The same happens if you use an initializer list like this:
MyClass(Type a): variable{} {
//...
}
Actually, variable is default initialized if you don't have any initializer list, so there is no reason to expect a different log.
I have a user defined class, say A. I have another user defined class B which publicly extends A.
When I define the constructor of B, I have to call the constructor of A in the member initializer list of B's constructor, or else the compiler will call the default constructor.
class A {
int a;
public:
A(int x = 0) {
a = x;
}
};
class B : public A {
int b;
public:
B(int x = 0) : A(2*x) {
b = x;
}
};
Now, I understand the logic behind all this. However, what I want to know is what happens when I do this instead:
class A {
int a;
public:
A(int x = 0) {
a = x;
}
};
class B : public A {
int b;
public:
B(int x = 0) {
A(2*x);
b = x;
}
};
I mean, we all know that the compiler will call the default constructor of A before it enters the body of the B's constructor. Now, the first line of B's constructor body is to call another constructor of A (which takes arguments). So, what does this result in? Two different constructors of the superclass are getting called here whenever an object of the subclass is being created. Please explain what happens...whether two objects will be created or what.
That doesn't call the constructor for the A subobject of the B being initialised. Instead, it creates and destroys a temporary object of type A. The only way to call the constructor of the base subobject is through the initialiser list, as in the first example.
Now, the first line of B's constructor body is to call another constructor of A (which takes arguments). So, what does this result in?
It constructs a temporary A and the temporary object is discarded right away. That call has no relationship to initializing the A part of B.