Calling virtual method from virtual destructor in C++ [duplicate] - c++

This question already has answers here:
Calling virtual method from destructor - workaround?
(4 answers)
Closed 5 years ago.
I want to destruct an object of class B.
class A {
public:
A() {
std::cout << "construct A" << av::endl;
a = new int;
}
virtual ~A() {
std::cout << "destruct A" << av::endl;
this->clear();
}
virtual void clear() {
std::cout << "clear A" << av::endl;
delete a;
}
protected:
int *a;
};
class B : public A {
public:
B() {
std::cout << "construct B" << av::endl;
b = new int;
}
~B() {
std::cout << "destruct B" << av::endl;
}
void clear() override {
std::cout << "clear B" << av::endl;
delete b;
delete this->a;
}
private:
int *b;
};
And I want it to be done with clear() method. But when I execute following code:
A *a = new B();
delete a;
I get:
construct A construct B destruct B destruct A clear A
And clear B is never printed.
What am I doing wrong?

Informally, In ~A(); the B part is already destroyed, calling any function of B doesn't make any sense.
Effective C++ Item 9: Never call virtual functions during construction or destruction.
Once a derived class destructor has run, the object’s derived class
data members assume undefined values, so C++ treats them as if they no
longer exist. Upon entry to the base class destructor, the object
becomes a base class object, and all parts of C++ — virtual functions,
dynamic_cast s, etc., —treat it that way.

Related

Virtual destructor, what would happen I didnt have a destructor in the derived class?

I've just had my lesson about virtual destructors and I have a question.
Lets say we have this code below:
#include <iostream>
class Base {
public:
virtual void fun() { std::cout << "Base Fun" << std::endl; };
virtual ~Base() { std::cout << "Base Destructor called" << std::endl; };
};
class Derived : public Base {
public:
virtual void fun() { std::cout << "Derived Fun" << std::endl; };
~Derived() { std::cout << "Derived Destructor called" << std::endl; };
};
int main()
{
Base* b = new Base();
Base* d = new Derived();
b->fun();
d->fun();
delete b;
delete d;
return 0;
}
We see that we have a Virtual destructor in our Base clase, which means when we delete d in our main, both the Base class destructor will be called and the Derived class destructor will be called..
**But what if we didnt have a destructor in our derived class, and we still wanted had the virtual destructor + we still wanted to delete d. What happens then? Does the derived class automatically "create" a destructor, and would the destructor then handle the ressource - d and delete it?
All classes have a destructor. If you don't write one explicitly, then compiler will implicitly generate it. Thus the case you are asking about "if I didn't have a destructor" doesn't exist.
and would the whole program still work as earlier?
It would work but not quite the same way since the implicitly generated destructor wouldn't print the string that your destructor prints.

Using address of variable inside constructor of class being reassigned [duplicate]

This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 4 years ago.
I have been debugging an issue involving an std::function (created from std::bind) where the issue boils down to a more fundamental question.
An example follows below, but in short it's about the case when a class in one way or another stores a pointer to itself (or an instance variable) in its constructor and the class itself is then reassigned. From my experiments it seems the stored pointer will then no longer point to the class (or its instance variable). I wonder what are the best practices to avoid these issues?
An example:
#include <iostream>
class Interface
{
public:
Interface() {};
virtual ~Interface() {};
virtual void callback() = 0;
};
class B
{
public:
B() : interface(NULL) {};
virtual ~B() {};
void set_interface(Interface* interface)
{
this->interface = interface;
}
void print()
{
std::cout << "B is at: " << this << std::endl;
std::cout << " Interface (A) from B is at: " << interface << std::endl;
}
private:
Interface* interface;
};
class A : public Interface
{
public:
A()
{
b.set_interface(this);
};
virtual ~A() {};
virtual void callback()
{
std::cout << "Callback" << std::endl;
}
void print()
{
std::cout << "A is at: " << this << std::endl;
b.print();
}
private:
B b;
};
int main(int argc, char** argv)
{
A a;
a.print();
std::cout << "------" << std::endl;
a = A();
a.print();
return 0;
}
When I run this on my machine I get:
A is at: 0x7ffdb8910af0
B is at: 0x7ffdb8910af8
Interface (A) from B is at: 0x7ffdb8910af0
------
A is at: 0x7ffdb8910af0
B is at: 0x7ffdb8910af8
Interface (A) from B is at: 0x7ffdb8910b10
So, at first everything is fine. The pointer to Interface from B points to the address of A. However, after reassigning (a=A()) the pointer to Interface no longer points to A! I realize this is because as the constructor of A is running to create the second instance, it is in a new memory location and stores the interface pointer to this new memory location. When a is then reassigned the object is moved in to the old location which invalidates the pointer to Interface.
This seems like a common use case to me. Should one always avoid referencing memory in constructors of objects?
In my case I would like to bind a callback function and pass it to a class member, it seems I cannot do it in the constructor then and must do it at a later time?
A is at fault:
A()
{
b.set_interface(this);
};
You define a constructor for A which handles a resource: itself. According to the rule of 0/3/5, A should have a user-defined copy constructor and an assignment operator, and if it makes sense, their move conterparts.
A()
{
b.set_interface(this);
};
A(A const&)
{
b.set_interface(this);
}
A& operator=(A const&)
{
b.set_interface(this);
return *this;
}

Virtual function behavior on statically declared objects [duplicate]

This question already has answers here:
What is object slicing?
(18 answers)
Closed 8 years ago.
Consider the following code:
class A {
public:
virtual void hello() { std::cout << "Hello from A" << std::endl; }
void hi() { std::cout << "Hi from A" << std::endl; }
};
class B : public A {
public:
void hello() { std::cout << "Hello from B" << std::endl; }
void hi() { std::cout << "Hi from B" << std::endl; }
};
int main() {
A foo = B();
foo.hello(); // prints "Hello from A"
foo.hi(); // prints "Hi from A";
A *bar = new B();
bar->hello(); // prints "Hello from B"
bar->hi(); // prints "Hi from A"
}
I'm aware that since hello() is declared as a virtual function in class A, any object of class B should have overridden behavior. However, why doesn't the object foo call the overridden hello()?
In other words, in what ways are the two object construction methods different? A foo = B(); v/s A *bar = new B()?
Thanks!
In the first case you're doing something wrong: slicing which is "cutting away part of the object" since you're assigning a derived object to a base object. You're not using virtual polymorphism because you're just calling methods on a "sliced" derived object (which isn't even safe).
Virtual polymorphism works with base class pointers to derived objects and virtual functions overriding, and that is a safe, runtime, mechanism to specialize your objects and call the appropriate methods.

c++ ctor and dtor don't work the same manner [duplicate]

This question already has answers here:
When to use virtual destructors?
(20 answers)
Closed 8 years ago.
I'm trying to figure out the tricks of class inheritance in C++ and I've built a sample project:
#include "stdafx.h"
#include <iostream>
using namespace std;
class A
{
public:
A()
{
cout << "Class A initialized" << endl;
}
~A()
{
cout << "Class A destructed" << endl;
}
};
class B : public A
{
public:
B()
{
cout << "Class B initialized" << endl;
}
~B()
{
cout << "Class B destructed" << endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
cout << "A* a = new A()" << endl;
A* a = new A();
cout << "B* b = new B ()" << endl;
B* b = new B ();
cout << "A* ab = new B()" << endl;
A* ab = new B();
cout << "delete a" << endl;
delete a;
cout << "delete b" << endl;
delete b;
cout << "delete ab" << endl;
delete ab;
int i;
cin >> i;
return 0;
}
The output I get is:
A* a = new A()
Class A initialized
B* b = new B ()
Class A initialized
Class B initialized
A* ab = new B()
Class A initialized
Class B initialized
delete a
Class A destructed
delete b
Class B destructed
Class A destructed
delete ab
Class A destructed
I can understand the behavior of class B as a derived class - first it constructs the base class and then the derived class. When it calls the destructor, it does the work the other way around. Seems logical.
What I can't understand, is the behavior of ab (allocation of B which I put into an A pointer),
why does the constructor act the same as pure B, but the destructor runs only on A?
Thanks.
The compiler calls member functions of the class that correspond to the static type of the pointer. The type of pointer ab is A * so the compiler calls the destructor of class A. If you would declare the destructor as virtual as for example
class A
{
public:
//...
virtual ~A()
{
cout << "Class A destructed" << endl;
}
};
then the compiler would use the table of vitual function pointers. In this case that is in the case of deleting ab the table would contain the pointer that refers to the destructor of the derived class.
As for the constructor then when you use operator new B() then the static type used in the expression is B. So the consttructor of B is called along with the constructor of A as the constructor of the base class.
There is a fundamental difference between constructors and destructors
(or constructors and any other function, for that matter): when
constructing an object, you must specify its exact type, in the source
code. For all other functions (including the destructor), it is
possible to only mention a base, provided certain conditions are met.
One of those conditions is that the function (or the destructor) be
virtual in the base class.
In the case of destructors, there is an additional constraint, because
the destructor is involved in a delete, which in turn requires the
address of the complete object in order to free the memory correctly.
Thus, given A* pA;, an expression like pA->f() will call the
function f in the base class if it is not virtual, but the function
f() in the derive class if it is virtual, and the derived class
overrides it. On the other hand, delete pA; will call the destructor
of the derived class if the destructor in the base is virtual, but is
undefined behavior if pA points to a derived class, and the
destructor in the base is not virtual. There is no question of just
9alling the destructor of the base class; although this might be the
actual behavior in simple cases, the behavior is undefined in all cases.
For this reason, it has often been recommended that if a class is
designed to be used as a base class, the destructor should be either
virtual, or protected. IMHO, it depends on the class: if anyone
misundertands std::exception<> to the point of writing something like:
std::exception<...>* pIter = new std::vector<...>::iterator;
// ...
delete pIter;
there's no hope, and it's not worth the bother of defining a destructor
for std::iterator, just to make it protected (and in pre-C++11, making
it impossible that the derived iterator be a POD).

Base class destructor is not virtual and child class destructor is virtual, program crash

Why does the following program crash? I have a base class whose destructor is not virtual but the child class destructor is virtual:
#include <iostream>
class Base {
public:
Base() {
std::cout << "Base::Base CTOR " << std::endl;
}
~Base() {
std::cout << "Base::Base DTOR " << std::endl;
}
};
class Child : public Base {
public:
Child(){
std::cout << "Child::Child CTOR " << std::endl;
}
virtual ~Child() {
std::cout << "Child::Child DTOR " << std::endl;
}
};
int main (int argc, char **argv) {
Base *ptr = new Child;
delete ptr;
}
What you are observing is called "undefined behavior". Make Base's dtor virtual if you want do call delete on Child instance through Base pointer.
From the 2003 standard, 5.3.5/3:
In the first alternative (delete object), if the static type of the
operand is different from its dynamic type, the static type shall be a
base class of the operand’s dynamic type and the static type shall
have a virtual destructor or the behavior is undefined.
You have undefined behavior because the static type of the pointer operand to delete does not match the dynamic type of the object that it points to and you don't meet the requirements for the exception to this rule that allows passing a pointer to a base class to the object being deleted because this exception requires the base class to have a virtual destructor.
Any behaviour is possible including the code working "as expected" or a crash.
Hope this example helps you get the point:
#include <iostream>
class Base {
public:
Base() {
std::cout << "Base::Base CTOR " << std::endl;
}
~Base() {
std::cout << "Base::Base DTOR " << std::endl;
}
private:
protected:
};
class Child : public Base {
public:
Child(){
std::cout << "Child::Child CTOR " << std::endl;
}
~Child(){
std::cout << "Child::Child DTOR " << std::endl;
}
private:
protected:
};
class gChild : public Child {
public:
gChild(){
std::cout << "Child::Child gCTOR " << std::endl;
}
~gChild(){
std::cout << "Child::Child gDTOR " << std::endl;
}
private:
protected:
};
int main ( int argc, char **argv) {
Base *ptr = new gChild;
delete ptr;
}
if virtual ~Base() ,then all destructors' print gets printed.
if virtual ~child() or virtual ~gChild(),only base destructor gets printed.
It's because the destructors executes in opposite direction.and here behaviour is undefined.You must define the base destructor virtual to get the expected result.
Thanks.
Just look at this:
#include <iostream>
class Base
{
public:
void nonvirtualmethod()
{ std::cout << "Base nonvirtualmethod" << std::endl; }
virtual void virtualmethod()
{ std::cout << "Base virtualmethod" << std::endl; }
};
class Derived: public Base
{
public:
void nonvirtualmethod()
{ std::cout << "Derived nonvirtualmethod" << std::endl; }
virtual void virtualmethod()
{ std::cout << "Derived virtualmethod" << std::endl; }
};
int main()
{
Derived d;
Derived* pd = &d;
Base* pb = &d; //< NOTE: both pd and pb point to the same object
pd->nonvirtualmethod();
pb->nonvirtualmethod();
pd->virtualmethod();
pb->virtualmethod();
}
I gives you the following output:
Derived nonvirtualmethod
Base nonvirtualmethod
Derived virtualmethod
Derived virtualmethod //< invoked by a Base*
This is because there is a difference between the static type of the pb pointer (Base*)
and the dynamic type it points to (Derived).
The difference between virtual and plain methods is that non-virtual methods follow the the static type mapping (so a Base pointer invokes Base::methods), while virtual methods follow the chain of the runtime types, hence if a Base* points to a Derived, the Derived method will be called.
Destructors, in this sense, are nothing special: if it is not virtual, a Base pointer will not invoke the Derived one, hence you are left with an half-destroyed object, that is given back to the memory store.
The reason why this is UB (and not simply denied), is because the "memory store" is not managed by the language itself, but from the platform the program is hosted in: the crash most likely depends on the fact that the missing of the Derived part (still alive) will result in the operating system trying free a block of memory with a wrong starting address.