im trying to understand the order of Constructor and Destructor calls when overwriting an object.
My code is :
class A
{
public:
A(int n): x(n)
{ cout << "A(int " << n << ") called" << endl; }
~A( )
{ cout << "~A( ) with A::x = " << x << endl; }
private:
int x;
};
int main( )
{
cout << "enter main\n";
int x = 14;
A z(11);
z = A(x);
cout << "exit main" << endl;
}
--
The output is :
enter main
A(int 11) called
A(int 14) called
~A( ) with A::xx = 14
exit main
~A( ) with A::xx = 14
--
Why is A::xx = 14 when the destructor is called? Shouldn't it be 11?
Why should it be 11? You reassign z to A(14), so it's 14 at the end.
(After your edit: You also see the destructor of the temporary A(14) object that gets destroyed at the end of the assignment.)
Related
I want to ask why the setX function here sets the x member variable in class A not the member variable x in class D even though I call setX function through D object?
How does the compiler did that ?
#include<iostream>
using namespace std;
class A
{
public:
int x;
A() { cout << "A cons" << endl; }
void setX(int i){ x = i; cout << "setxA" << endl; }
void print() { cout << x; }
};
class B : public A
{
public:
int x =30;
B() { cout << "B cons" << endl; }
};
class D : public B {
public:
D() {
cout << "D cons" << endl;
}
void func() {
setX(10);
cout << x << endl;
cout << B::x << endl;
cout << A::x << endl;
}
};
int main()
{
D d;
d.func();
return 0;
}
the output from this code is
30
30
10
This is called name hiding. Both A and B have a member x and both members always exist (you just cannot access them the same way). A knows about his member x and so the setX function sets exactly this member A::x. In B, you define another x which hides A::x. This means that if you do
B obj;
obj.x = 10;
or
D obj;
obj.x = 10;
you will access B::x both of the times (because B is lower in the inheritance hierarchy and therefore hides A::x).
Here is an example of how you can still access A::x using different casts.
#include <iostream>
struct A {
int x = 0;
void setX(int i) { x = i; }
};
struct B : A {
int x = 20;
};
int main()
{
B obj;
A castToA = static_cast<A>(obj);
A* castToAPtr = reinterpret_cast<A*>(&obj);
std::cout
<< "access via B: " << obj.x << "\n"
<< "access via A: " << castToA.x << "\n"
<< "access via A*: " << castToAPtr->x << "\n"
<< "access via B::(A::x): " << obj.A::x << "\n\n";
obj.setX(100);
std::cout << "set x to 100\n\n";
std::cout
<< "access via B: " << obj.x << "\n"
<< "access via A: " << castToA.x << "\n"
<< "access via A*: " << castToAPtr->x << "\n"
<< "access via B::(A::x): " << obj.A::x << "\n\n";
return 0;
}
which yields the output:
access via B: 20
access via A: 0
access via A*: 0
access via B::A::x: 0
set x to 100
access via B: 20
access via A: 0
access via A*: 100
access via B::A::x: 100
Your class B has an x and also A has an X. As this, you have two x in B!
So you may remove the x from your B class?
If you need both, you can access them with
A::x or B::x inside a method of B which you already did.
So your D class have also both x and calling setX calls the setX method of A. As in D you see the x from B which hides your x from A everything works as expected.
Your method A::setX did not know that you derive later from it. If you want to override the method, B has define a own B::setX which will then also be used in D.
Example how to override a method and access the parameter in derived class:
class A
{
public:
int x; // A::x
int y = 40; // A::y
// this function only knows about A::x
void setX(int i){ x = i; cout << "setxA" << endl; }
void setY(int i){ y = i; cout << "setyA" << endl; }
};
class B : public A
{
public:
int x =30; // this x ( B::x) hide A::x
int y =50; // this y hides also A::y
// now we override setY from A ( hiding setY from A! )
void setY(int i){ y = i; cout << "setyB" << endl; }
};
class D : public B {
public:
void func() {
setX(10); // Calls A::setX, as A::setX only knows about
// A::x it will access A::x
cout << "X" << std::endl;
cout << x << endl;
cout << B::x << endl;
cout << A::x << endl;
setY(90);
cout << "Y" << std::endl;
cout << y << endl;
cout << B::y << endl;
cout << A::y << endl;
}
};
int main()
{
D d;
d.func();
return 0;
}
I've noticed some behaviour which I can't understand in parameterized constructors. Given the following program:
#include <iostream>
using namespace std;
class A {
public:
int x;
A() {}
A(int i) : x(i){
cout << "A\n";
}
~A(){
cout << "dA\n";
}
};
int main(){
A p;
p = 3;
cout << p.x << endl;
p = 5;
cout << p.x << endl;
return 0;
}
I get as output:
A
dA
3
A
dA
5
dA
This means that using = triggers the parameterized constructor, destroys the object on which it's called and creates a new object.
I cannot understand this behaviour and I can't find the answer in the standard ( I am sure it is there somewhere, but it may be stated in a sophisticated way). Could someone help me with an explanation?
The phrase you're probably looking for is "implicit conversion".
If you add a copy constructor and an assignment operator, and then give each object a unique ID, it's easier to see where things go:
int counter = 0;
class A {
public:
int id;
A(): id(++counter) {cout << "A(): " << id << "\n";}
A(int i) : id(++counter) {cout << "A(" << i << "): " << id << "\n";}
// Don't copy the id.
// (This isn't used anywhere, but you can't see that it's not used unless it exists.)
A(const A& a) : id(++counter) {cout << "A(" << a.id << "): " << id << "\n";}
// Don't copy the id here either.
A& operator=(const A&a) {cout << id << " = " << a.id << "\n"; return *this;}
~A(){cout << "destroy: " << id << "\n";}
};
int main(){
A p;
cout << "p is " << p.id << "\n";
p = 3;
cout << "p is " << p.id << "\n";
p = 5;
cout << p.id << "\n";
}
Output:
A(): 1
p is 1
A(3): 2
1 = 2
destroy: 2
p is 1
A(5): 3
1 = 3
destroy: 3
1
destroy: 1
As you can see, the parameterized constructor is used to create a temporary object whose value can be assigned to p, and that temporary is destroyed immediately after that.
You can also see that p is alive and well until the very end.
With a statement like
p = 3;
what you're actually doing is
p = A(3);
which really translates to
p.operator=(A(3));
The temporary A object created by A(3) of course needs to be destructed, it is temporary after all.
The object p itself will not be destructed by the assignment.
I cannot understand the order of constructor and destructor calls? What will execute first in this statement A b=f(a)? Can someone please help me out?
#include<iostream>
using namespace std;
class A {
int x;
public:
A(int val = 0)
:x(val) {
cout << "A " << x << endl << flush;
}
A(const A& a) {
x = a.x;
cout << "B " << x << endl << flush;
}
void SetX(int x) {
this->x = x;
}
~A() {
cout << "D " << x << endl << flush;
}
};
A f(A a) {
cout << " C " << endl << flush;
a.SetX(100);
return a;
}
int main()
{
A a(1);
A b=f(a);
b.SetX(-100);
return 0;
}
Output Window:
A 1
B 1
C
B 100
D 100
D -100
D 1
Why does it print B 1 in line 2 of the output window?
"Why does it print B 1 in line 2?"
Because the copy constructor was called from this statement
A b=f(a);
The function f() requires A being passed by value, thus a copy for this parameter is made on the function call stack.
If your next question should be, how you can get over this behavior, and avoid to call the copy constructor, you can simply pass the A instance as a reference to f():
A& f(A& a) {
// ^ ^
cout << " C " << endl << flush;
a.SetX(100);
return a;
}
Side note: endl << flush; is redundant BTW, std::endl includes flushing already.
When an instance variable is inherited, changing it in the subclass does not affect its value in the superclass and vise versa. That implies that there are two instance variables. But when I do sizeof( sublcass ), only one instance variable is accounted for in the size. So is there a second object that gets created for the superclass ?
Here's a small snippet to illustrate what I'm saying:
struct Super {
int x;
void func() {
cout << "SUPERCLASS" << endl;
cout << x << endl; /* prints garbage value */
x = 4;
cout << x << endl; /* prints 4 */
}
};
struct Sub : public Super {
void func() {
x = 10;
Super b;
b.func();
cout << "SUB" << endl;
cout << x << endl; /* prints 10 */
}
};
int main() {
Sub b;
b.func();
return 0;
}
The output:
SIZE: 4
SUPERCLASS
2867344
4
SUB
10
In this function, you create a new object of type Super and print it.
void func() {
x = 10;
// b is now a totally different (and unrelated object)
// so calling b.func() will print the x variable that
// is valid for that instance (not this instance)
Super b;
b.func();
cout << "SUB" << endl;
cout << x << endl; /* prints 10 */
}
Your assumption is actually incorrect, there is only one instance variable x that lives within your class Sub. Your function Sub::func() has hidden Super::func() and in order to call it, you need to directly call it using the scope resolution operator (::).
void func() {
// this is the one (and only) x that is in scope
// inherited by `Sub` from `Super`.
x = 10;
// call Super::func(), using the scope resolution operator
Super::func();
cout << "SUB" << endl;
cout << x << endl; /* prints 10 */
}
If you just make usage of data members explicit you should see where the issue is:
void func() {
this->x = 10;
Super b;
b.func();
cout << "SUB" << endl;
cout << this->x << endl; /* prints 10 */
}
As this is obviously not equal to &b you should clearly see that you are accessing members of different objects.
I want to write a library wrapper class (LibWrap) around a C library that uses malloc/free. To do this I want to use C++'s RAII to allocate and free memory. I used lib_address as a random example address that I would receive from the library. However when defining my memeber variable the destructor that is called somehow has this lib_address.
I would expect the destructor of the member variable created by the default constructor not to know the new address that I am putting into the constructor of my replacement member variable.
#include <stdlib.h>
#include <iostream>
using namespace std;
class LibWrap
{
int j;
int lib_address;
public:
LibWrap(): //default LibWrap
j(0),
lib_address(0)
{
cout << "default LibWrap "<<j <<"\t\t"<<lib_address << "\t" << this<<endl;
}
LibWrap(int f_j): //special LibWrap
j(0),
lib_address(0)
{
j = f_j;
lib_address = rand();
cout << "special LibWrap " << j<<"\t"<< lib_address<< "\t" << this <<endl;
}
~LibWrap()
{
cout << "killing LibWrap " << j<<"\t" <<lib_address <<"\t" << this<< endl;
}
int g()
{
return j;
}
};
class A
{
int i;
LibWrap b;
public:
A(): //default A
i(0)
{
cout << "default A\t"<<i << endl;
}
A(int f_i)://special A
i(0)
{
i = f_i;
cout << "special A\t"<<i << endl;
b = LibWrap(10);
}
~A()
{
cout << "killing A\t"<<i << endl;
}
void p()
{
cout <<"Test values: "<< i<< "," << b.g() << endl;
}
};
int f()
{
//A a; a.p();
cout << "variable\t\tlib_address\treal_address" << endl;
A a = A(1);
cout << "End" << endl;
//a.p();
}
int main()
{
f();
}
Running this code I would expect to get the following result:
variable lib_address real_address
default LibWrap 0 0 0xbfef2e28
special A 1
special LibWrap 10 1804289383 0xbfef2df8
killing LibWrap 10 1804289383 0xbfef2df8 --would expect kiling LibWrap 0 0 0xbfef2e28
End
killing A 1
killing LibWrap 10 1804289383 0xbfef2e28 --would expect killing LibWrap 10 1804289383 0xbfef2df8
b = LibWrap(10);
This does not initialize b. b has already been initialized as part of constructing A. What you're doing is creating a temporary LibWrap and copying that temporary into b. Then, you're destroying that temporary LibWrap (which is where the extra destructor call with the lib_address comes from).
The temporary LibWrap is where the "0xbfef2df8" address comes from. The b variable is the "0xbfef2e28" address. That's why you're getting them in that order.