#include <iostream>
using namespace std;
#define debug(x) cout << #x << ": " << (x) << endl;
class Base {
public:
void f() { cout << "Base:f()" << endl; }
~Base() { cout << "Base:~Base()" << endl; }
};
class A : public Base {
public:
~A() { cout << "A:~A()" << endl; }
};
int main() {
{
A a;
static_cast<Base>(a);
}
return 0;
}
In this code
I call the static_cast to covert the A to Base,
the output tells me that it calls the ~Base() twice?
why the static_cast make the destructor be called?
static_cast<Base>(a); constructs a temporary Base, which is copied from a. After the full expression the temporary gets destroyed, the destructor of Base is called.
After that, when get out of the scope a gets destroyed, the destructor of A and Base are called in order. Note that this has nothing to do with the static_cast.
Related
I attempt to modify the vfptr of a Base object to point to vtable which class Derived owns:
#include<iostream>
using namespace std;
class Base {
public:
virtual void func() { cout << "Base::func()" << endl; }
Base() = default;
Base(const Base&);
};
Base::Base(const Base&b) {
*((int*)(this)) = *((int*)(&b)); //modify the vfptr
}
class Derived : public Base {
public:
virtual void func() { cout << "Derived::func()" << endl; }
};
int main() {
Derived d;
cout << "Derived's vtable: " << *(int*)&d << endl << endl;
Base b = d;
cout << "Base's vtable: " << *(int*)&b << endl << endl;
cout << "pass by value:" << endl;
b.func();
cout << endl;
Base *bp = &b;
cout << "pass by pointer" << endl;
bp->func();
}
Output in VS2017:
Derived's vtable: 9739088
Base's vtable: 9739088
pass by value:
Base::func()
pass by pointer
Derived::func()
We can see that vfptr of object b does point to the Derived vtable after modifing but still call the Base version func() by value.
I wonder if the compiler handles such value-call by static binding even if what is called is a virtual function?
Thank you so much.
I wonder if the compiler handles such value-call by static binding
Base b = d;
b.func();
Yes, it does do static binding here indeed. In fact, using dynamic binding would be pointless because the dynamic type of the object is known to be the same as the static type at compile time.
In the following code, how can I access Base::g() from pBase? (and still get "pBase->g();" to work as it does below)
#include <iostream>
using namespace std;
class Base
{
public:
virtual void f(){ cout << "Base::f()" << endl; }
virtual void g(){ cout << "Base::g()" << endl; }
void h(){ cout << "Base::h()" << endl; }
};
class Derived : public Base
{
public:
void f(){ cout << "Derived::f()" << endl; }
virtual void g(){ cout << "Derived::g()" << endl; }
void h(){ cout << "Derived::h()" << endl; }
};
int main()
{
Base *pBase = new Derived;
pBase->f();
pBase->g();
pBase->h();
Derived *pDerived = new Derived;
pDerived->f();
pDerived->g();
pDerived->h();
return 0;
}
Output is:
Derived::f()
Derived::g()
Base::h()
Derived::f()
Derived::g()
Derived::h()
Also, is Derived::f() exactly the same as Derived::g()? (ie. automatically defined as virtual?)
Use pBase->Base::g(); to force the call of g in Base.
Yes, Derived::f is virtual. I personally find the re-emphasising of virtual to be in poor taste. Since C++11, you can use the override specifier on overridden functions, and then a compiler issues a diagnostic if virtual is dropped from the base class.
The following is an abstract of my code:
Base class:
#include <iostream>
using namespace std;
class Base {
public:
Base() { cout << "Base constructor" << endl; }
~Base() { cout << "Base destructor" << endl; }
virtual void func(void) const { cout << "base" << endl; }
};
Derived class:
#include "Base.h"
class Derived : public Base {
public:
Derived() { cout << "Derived constructor" << endl; }
~Derived() { cout << "Derived destructor" << endl; }
void func(void) const { cout << "derived" << endl; }
};
Test class:
#include "Derived.h"
class Test {
public:
const Base& base;
Test(const Base& _base) : base(_base) { cout << "Test constructor" << endl; }
void test() { base->func(); }
~Test() { cout << "Test destructor" << endl; }
};
main function for testing:
#include "Test.h"
int main(void) {
Test* t = new Test(Derived());
t->test();
return 0;
}
When I run the main function, the Base version of func is being called.
However, if I change the main function to the following:
#include "Test.h"
int main(void) {
Derived d;
Test* t = new Test(d);
t->test();
return 0;
}
The Derived version of func is correctly called.
I also tried to change const Base& base in Test to Base* base. And then construct Test using
Test* t = new Test(new Derivec())
It turns out that the Derived version of func is also correctly being called.
I was thinking that if I use either reference or pointer, the polymorphism is going to work.
Can anyone explain to me why the first version does not call the derived class method correctly?
Thanks a lot for helping!
You have a dangling reference problem.
Test* t = new Test(Derived());
You are using a temporary object of type Derived to construct t. The temporary object gets deleted after the constructor of Test returns.
Hence, your program has undefined behavior.
If you use
Derived d;
Test* t = new Test(d);
you get the expected behavior because t does not have a dangling reference.
Also note that
void test() { base->func(); }
should not compile since base is a reference. That lines needs to be:
void test() { base.func(); }
I have the following program:
#include<iostream>
using namespace std;
class A {
protected:
A() { cout << "Executing A()" << endl; }
public:
~A() { cout << "Executing ~A()" << endl; }
};
class B : public A {
public:
B() { cout << "Executing B()" << endl; }
~B() { cout << "Executing ~B()" << endl; }
};
class C : public B {
public:
C() { cout << "Executing C()" << endl; }
~C() { cout << "Executing ~C()" << endl; }
};
void someFunc() {
A a = C();
}
int main() {
someFunc();
return 0;
}
which prints the following:
Why is ~A() called twice?
The destructor for A is called twice because there are two objects that need to be destroyed. By printing something when the copy or move constructor is called you can verify this:
class A {
protected:
A() { cout << "Executing A()" << endl; }
public:
A(const A &) { cout << "Executing A(const A &)" << endl; }
// with recent compilers, you could also try A(A &&)
~A() { cout << "Executing ~A()" << endl; }
};
Output:
Executing A()
Executing B()
Executing C()
Executing A(const A &)
Executing ~C()
Executing ~B()
Executing ~A()
Executing ~A()
Basically, A a = C(); doesn't do what you might think it does. It creates an anonymous C object, and then creates a as an A object, copying from the just-created anonymous object. It does not let a somehow point to a real C object.
A variable declared as A is always an A, never any derived type. To get something to that effect, you would need to use pointers or references.
const A &a = C();
Here, a is not an A object. This creates the same anonymous C object as before, but then makes a a reference to that anonymous object, instead of attempting to create a new A object.
hey there, why is the base destructor called twice at the end of this program?
#include <iostream>
using namespace std;
class B{
public:
B(){
cout << "BC" << endl; x = 0;
}
virtual ~B(){
cout << "BD" << endl;
}
void f(){
cout << "BF" << endl;
}
virtual void g(){
cout << "BG" << endl;
}
private:
int x;
};
class D: public B{
public:
D(){
cout << "dc" << endl; y = 0;
}
virtual ~D(){
cout << "dd" << endl;
}
void f(){
cout << "df" << endl;
}
virtual void g(){
cout << "dg" << endl;
}
private:
int y;
};
int main(){
B b, * bp = &b;
D d, * dp = &d;
bp->f();
bp->g();
bp = dp;
bp->f();
bp->g();
}
Destructors are called in order, as if they were unwinding the effects of the corresponding constructors. So, first the destructors of the derived objects, then the destructors of the base objects. And making the destructors virtual doesn't have any impact on calling / not calling the base class destructor.
Also to mention, your example could be simplified this way (this code also results in calling the base destructor twice and the derived destructor once):
struct A {
~A() {
// ...
}
};
struct B: A {
~B() {
// ...
}
};
int main() {
A a;
B b;
}
Once it is called for b and once for d
Note when destructor of D called it is automatically calls the destructor of B it is different from ordinary virtual functions. where you need explicitly call base class function to use it.