What should the following code do and with explanations - c++

class A {
public:
A() { }
~A() { cout << "A Destructor \n" ; }
};
class B :public A{
public:
B() { }
virtual ~B() { cout << "B Destructor \n" ; }
};
class C : public B {
public:
C() { }
~C() { cout << "C Destructor \n"; }
};
int main()
{
A *pointA = new A;
A *pointB = new B;
A *pointC = new C;
delete pointA;
delete pointB;
delete pointC;
}

It will invoke undefined behavior at the second (and third) delete, because A's destructor is not virtual.
§5.3.5/3:
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.
If you make the destructor of A virtual, you get well-defined behavior, and the destructor of the dynamic type is called. (And each of those in turn calls the base destructor.) Your output would be:
A destructor
B destructor
A destructor
C destructor
B destructor
A destructor
For what it's worth, when you're that close to a compilable snippet, you should leave the includes. Also, just use struct instead of class to be concise about the public stuff, and leave out empty constructors.

As GMan pointed out, attempting to call the delete operator on a base pointer requires a virtual destructor for the compiler to be able to destroy subclass objects correctly. A lot of people oversimplify this to a rule like, "If a class has virtual functions, it needs a virtual destructor." That is not necessarily the case; even a base class which has no virtual functions still needs a virtual destructor if you want to allow clients to delete the class through a base pointer. If you don't, the destructor should be protected and not public.
There is an excellent book that describes this in detail and more called C++ Coding Standards by Herb Sutter. I recommend it as a starting point in your C++ adventures. :-)

Related

Is it necessary to have virtual destructor if the derived class only contains automatic variable members?

struct base
{
base(){}
~base() { cout << "base destructor" << endl; }
};
struct derived : public base
{
derived() : base() { vec.resize(200000000); }
~derived() { cout << "derived destructor" << endl; }
vector<int> vec;
};
int main()
{
base* ptr = new derived();
delete ptr;
while (true)
{
}
}
The above code leaks due to delete operation not calling derived object's destructor. But...
struct base
{
base() {}
~base() { cout << "base destructor" << endl; }
};
struct derived : public base
{
derived() : base() {}
~derived() { cout << "derived destructor" << endl; }
int arr[200000000];
};
int main()
{
base* ptr = new derived();
delete ptr;
while (true)
{
}
}
In second case, the memory doesn't leak despite the base destructor is only being called. So I'm assuming it's safe to not have a base destructor if all my members are automatic variables? Doesn't 'arr' member in derived class never go out of scope when derived object's destructor is not being called? What's going on behind the scenes?
YES!
I see that you are thinking "practically", about what destructions might be missed. Consider that the destructor of your derived class is not just the destructor body you write — in this context you also need to consider member destruction, and your suggestion may fail to destroy the vector (because the routine non-virtually destroying your object won't even know that there is a derived part to consider). The vector has dynamically allocated contents which would be leaked.
However we don't even need to go that far. The behaviour of your program is undefined, period, end of story. The optimiser can make assumptions based on your code being valid. If it's not, you can and should expect strange sh!t to happen that may not fit with how your expectation of a computer should work. That's because C++ is an abstraction, compilation is complex, and you made a contract with the language.
It is always necessary to have a virtual destructor in a base class if a derived object is ever deleted through a pointer to that base. Otherwise behaviour of the program is undefined. In any other case it is not necessary to have a virtual destructor. It is irrelevant what members the class has.
It's not necessary to have a memory leak and still invoke an UB. Memory leak is a kind of expected UB if your derived class isn't trivial. Example:
#include <iostream>
class Field {
public:
int *data;
Field() : data(new int[100]) {}
~Field() { delete[] data; std::cout << "Field is destroyed"; }
};
class Base {
int c;
};
// Derived class, contains a non-trivial non-static member
class Core : public Base
{
Field A;
};
int main()
{
Base *base = new Core;
delete base; // won't delete Field
}
he C++ Standard, [expr.delete], paragraph 3 states (2014 edition)
In the first alternative (delete object), if the static type of the
object to be deleted is different from its dynamic type, the static
type shall be a base class of the dynamic type of the object to be
deleted and the static type shall have a virtual destructor or the
behavior is undefined. In the second alternative (delete array) if the
dynamic type of the object to be deleted differs from its static type,
the behavior is undefined.
In reality , if base class is trivial, all fields are trivial and derived class contains no non-static or non-trivial members, one might argue, that those classes are equal, but I'm yet to find way how to prove that through standard.It's likely an IB instead of UB.

What is the bug inside this C++ code?

I believe It's C++ but it may be C? Its been a while since I looked at C++ so I didn't end up finding the bug. I was asked this question in an interview and didn't have an answer. I obviously didn't get the job but now I'm curious to find the answer.
#include<iostream>
class Base {
public:
Base() {
std::cerr<<"constructing Base " << this << std::endl;
i = new int;
}
~Base() {
std::cerr<<"destroying Base " << this << std::endl;
delete i;
}
private
int* i;
};
class Derived : public Base {
public:
Derived() {
std::cerr<<"constructing Dervied " << this << std::endl;
d = new double;
}
~Derived() {
std::cerr<<"destroying Derived " << this << std::endl;
delete d;
}
private
double* d;
};
int main(int argc, char** argv) {
using namespace std;
int ret = 1;
Base* thePtr = new Derived;
delete thePtr;
return ret;
}
Thanks in advance!
The Base's destructor is not virtual. This will leak the Derived::d pointer, at best.
Actually, it's undefined behaviour to delete a pointer of derived class through a base class pointer without virtual destructor (thanks to GManNickG)
You should mark Base class destructor as virtual. In your code Base class destructor isn't virtual & base class pointer is pointing to Derived class object so by default destructor will be called of Base class unless it is marked as virtual. This will leak dynamically allocated memory of Derived class data member d & invokes undefined behaviour.
Let me make a list...
Base destructor is not virtual.
It's using raw pointers instead of smart pointers
In fact, it doesn't need pointers, new and delete at all
And therefore, it doesn't actually need destructors.
Also Derived is spelled Dervied
... and it won't compile.
Your base class destructor should be declared virtual, it looks like
cpp
virtual ~Base()
{
std::cerr<<"destroying Base " << this << std::endl;
delete i;
}
you can find it here http://www.programmerinterview.com/index.php/c-cplusplus/virtual-destructors/
Virtual destructors are useful when you can delete an instance of a derived class through a pointer to base class:
there is a major problem with the code above: the destructor for the "Derive" class does not get called at all when we delete basePtr,
The construction of derived object follow the construction rule but when we delete the "b" pointer(base pointer) we have found that only the base destructor is call.But this must not be happened.
To do the appropriate thing we have to make the base destructor virtual. it's similar to the run-time polymorphism, so that the compiler will find this is a base pointer but point to the derived class, and automatically bound derived class destructor for it

Friendliness and inheritance

Suppose i have this code:
#include <iostream>
using namespace std;
class A
{
protected:
virtual ~A() { cout << "A destructor reached." << endl;}
friend class Z;
};
class B : public A
{
protected:
virtual ~B() { cout << "B destructor reached." << endl; }
};
class Z
{
public:
void Test();
friend class A;
};
void Z::Test()
{
A* derived = (A*) new B();
delete derived;
}
int main()
{
Z test;
test.Test();
}
What is going to happen, will the B destructor be called? Is it legal? And if it's not, is there any way to call the derived constructor without making every class derived from A friend of Z?
The Standard, §11.5/1 "access to virtual functions," says
The access rules (Clause 11) for a virtual function are determined by its declaration and are not affected by the rules for a function that later overrides it.
So you can call B::~B as long as you have access to A::~A. But you must call it through A because Z does not have access to B.
By the way, the friend declaration in Z is useless since nothing is private or protected in it.
There are at least two questions involved here.
Yes, B's destructor will be called. That's how polymorphism works, that's how virtual destructors work, it's by design and it's a good thing.
The fact that a member function that is protected (or even private) in B but virtual and available (e.g. public) in A can be invoked via A* may seem a little odd at first, but it's by design too. What's the alternative? The only other option I can see would be to forbid inheritance that increases the restriction of a virtual member function; what good purpose would that serve?
If you don't want a method to be accessible, don't derive it from an accessible virtual parent method.

Will "delete this" in a base class pointer delete the derived class object when you have a virtual destructor?

I have a class hierarchy that's three levels deep, like this:
class A {
public:
virtual ~A() {}
}
class B : public A {
public:
virtual ~B() {}
void foo(E *e) {
e->remove(this);
}
}
class C : public B {
public:
~C() {}
}
class E {
public:
void remove(A *a) {
delete a;
}
}
Ok so what I am wondering is what happens when I call foo() on an object of C. Is it going to remove the entire object or only the B and A part of the object, and leave the C part still in memory?
Is it going to remove the entire object or only the B and A part of the object, and leave the C part still in memory?
No. It will "do the right thing" (that is, delete the most derived subobject, run all its destructors etc.) provided A (that is, the static type of the pointee of the pointer you delete) has a virtual destructor (and if class A has a virtual destructor, all its descendants have it, too). This holds for multiple inheritance, too.
Thanks to the virtual destructor in A the code would work correctly destroy the entire instance of C.
delete will always release the memory for the whole object pointed to.
This doesn't apply to called destructors however: It will try to call the destructor of the static type of the object to delete.
In a polymorphistic scenario, this is often not what you want. Consider this:
struct Base { };
struct Derived : Base
{
int* i;
Derived() : i(new int) { }
~Derived() { delete i; }
}
void bad()
{
Base* b = new Derived;
delete b;
}
bad() causes a memory leak, because Deriveds destructor will never be called. This is because the static type of b is Base*, thus Base::~Base will be called. There is no destructor defined in Base, so the default implementation provided by the compiler executes, which does nothing in this particular example.
This however does not apply to your example: You made the root class' destructor virtual, so all derived classes' destructors will be executed as part of the destructor call.

How 'delete' works when I delete a pointer of base class

#include <iostream>
using namespace std;
int *p1;
struct base
{
base():a(10){}
int a;
~base()
{
cout << "~base()\n";
}
};
struct derive:public base
{
derive():b(5){
p1=&b;
cout << p1 << "\n";
}
int b;
~derive()
{
cout << "~derive()\n";
}
};
int main()
{
base *p = new derive;
delete(p);
cout << *p1;
return 0;
}
I think b of derive shoule not be deleted,but what p1 pointed was deleted.
how it works when I delete pointer of a base class that was pointed to an derive class when no dynamic inherit occured?
sorry for my english.
It's undefined behavior, because the base class destructor is not virtual. UB means anything can happen.
Don't delete a derived object through a base class if the base class doesn't have a virtual destructor.
What one would expect with following code
base *p = new derive;
delete(p);
is that the derive object pointed to by p is cleaned up correctly.
This can only be done when the base class has a virtual destructor. This is not the case here, so whatever cleanup that happens in the derive destructor will not happen, which is an unhealthy situation (or as put more technically by Luchian: undefined behavior).
I am not 100% I understand the question, and it has been awhile since ive used c++, but I will give it a shot.
Generally if you have an object that is going to be allocated dynamically you need to have 3 things, that my teachers used to call "The trilogy of evil".
Copy Constructor
Assignment Operator
Virtual Destructor
the first two have to do with making "deep copies" while the third is what we are concerned with.
You need to mark your destructor virtual to add it to the objects virtual table, that way the destructors will call up a chain.
so:
class A
{
public A(A & copy) { ... }
public static A & operator = (A & rhs) { ... }
virtual ~A() { ... }
}
class B : A { } // inherits A's destructor via virtual table