struct Base{
int hp = 1000;
virtual ~Base()
{
std::cout << "Base destructor\n";
}
};
struct Child : Base {
int hp = 100;
virtual ~Child()
{
std::cout << "Child destructor\n";
}
};
int main()
{
std::vector<Base*>vct;
for(int x=0;x<25;x++)
{
vct.push_back(new Child);
}
std::cout << vct[3]->hp;
return 0;
}
I have written this program, which creates 25 objects of type Child, yet when run, both the destructors of the child and base class are called, which would imply that the 'new child' call would create an instance of both the child, and the base class. Why?
Furthermore, trying to access the int "hp" of any of the members of the vector, always returns 1000, not 100, which indicates that all the vector members are of type Base, not of type Child.
So in short, what do I need to do to 1. only create Child objects, not Base(even having the Base class as an abstract class still, somehow, seems to create objects of it) 2. Have all the members/elements of the vector to be of the child class, when the type of the vector is Base*
This is exactly how C++ inheritance works. Even if you didn't explicitly define a constructor, the parent class's default constructor still runs. In this case, the default constructors are mostly a no-op save for the member initialization of hp in both.
Both Child destructor and Base destructor get printed because you declared your destructor (correctly) as virtual. However, you aren't explicitly deleting any instance of objects you are allocating via new, so I'm not sure how you are seeing any print statements at all.
The hp in Child shadows the hp in Base, but member variables are not virtual. So when you access hp via Base class pointer, you get the Base class member. If you want to have the derived class access to hp, mark hp as protected in Base, and set in constructor in derived. In you case, everything is a struct, so all members are already public.
struct Base{
int hp = 1000;
virtual ~Base()
{
std::cout << "Base destructor\n";
}
};
struct Child : Base {
Child()
{
hp = 100; // Base constructor has already run, so we override here
}
virtual ~Child()
{
std::cout << "Child destructor\n";
}
};
int main()
{
std::vector<Base*>vct;
for(int x=0;x<25;x++)
{
vct.push_back(new Child);
}
std::cout << vct[3]->hp;
// let's delete explicitly and avoid the leak.
for(int x=0;x<25;x++)
{
delete vec[x];
vec[x] = nullptr; // not necessary, but is a good practice
}
return 0;
}
Related
I create a object of derived class and a base class point for it ,
and then I use the dynamic_cast convert base class point to derived class point .
I delete the derived class point , but the program calls the derived destructor and the base destructor. Why does the program call the base destructor? After all, the base destructor isn't a virtual function....
#include<iostream>
#include<stdlib.h>
using namespace std;
class con {
private:
double num;
public:
con() {
num = 0;
cout << "default..." << endl;
}
void getnum() {
cout << num << endl;
}
};
class base {
public:
virtual void A() {
cout << "it is base A" << endl;
}
void B() {
cout << "it is base B" << endl;
}
~base() {
cout << "it is base decon" << endl;
}
};
class child : public base {
public:
void A() {
cout << "it is child A" << endl;
}
void B() {
cout << "it is child B" << endl;
}
~child() {
cout << "it is child decon" << endl;
}
};
int main(int argc, char** argv) {
base* b = new child();
child* c = dynamic_cast<child*>(b);
delete c; //the program print "it is child decon" "it is base decon"
getchar();
return 0;
}
Case 1: If you delete a pointer derived class, it always calls the destructor of the derived class first, then the destructor of the base class.
Case 2: If you delete a pointer to the base class of a derived class with a non-virtual base class destructor, it doesn't know about the derived class so it just deletes the base class.
Case 3: If you delete a pointer to the base class of a derived class with a virtual base class destructor, it uses virtual dispatch to the destructor of the derived class, then calls the destructor of the base class.
Case 2 is bad. It can cause resource leaks, etc. It should be avoided by always declaring destructors virtual in classes that are intended to be base classes.
Your example illustrates case 1.
If you want to see case 2 in action try delete b rather than delete c in your example.
Destructors in C++ don't "overload" as such; they chain up. When you say
{
child c;
}
then at the closing brace the compiler will insert a call to ~child(), which will in turn call ~base() (and the destructors of other base classes, if you had them). This is essential to avoid memory leaks -- otherwise how would base's members be destroyed? Note that this doesn't require the base destructor to be virtual.
This works the same way when you manually destroy something with delete:
child* c = new child{};
delete c; // runs ~child(), which calls ~base()
again, this doesn't require the destructor to be virtual.
What a virtual destructor does do is allow you to destroy a variable with dynamic type child using a pointer to a base, i.e.
child* c = new child{}
base* b = c;
delete b; // Will call ~child() if destructor is virtual, otherwise ~base()
i have a basic and simply question.
I have this scenario:
#include <iostream>
using namespace std;
class Inner1
{
public:
~Inner1() {cout << "Inner1 Des\n";};
};
class Inner2
{
public:
~Inner2() {cout << "Inner2 Des\n";};
};
class Base
{
public:
~Base() {cout << "Base Des\n";};
Inner1 inner1;
Inner2 inner2;
};
int main() {
Base base;
return 0;
}
And my console tells me now this:
Base destructor called
Inner2 destructor called
Inner1 destructor called
Is this the normal behavior? Because the functionality for some functions
is already destroyed in my Base Class destructor and the Inner classes rely
on them.
Not recommended workaround:
Just add a "Destroyer" class with object at the first position:
[...]
class Base
{
public:
~Base() {cout << "Base Des\n";};
class Destroyer
{
~Destroyer()
{
//Put the stuff here because this destr will be called last
cout << "Destroyer Des\n";
}
} _destroyer;
Inner1 inner1;
[...]
Thank you for your help
Is this the normal behavior?
Yes. Subobject destructors are called by the destructor of the container class. In particular, the subobjects will be destroyed after the body of the container classes destructor has been executed.
Because the functionality for some functions
is already destroyed in my Base Class destructor and the Inner classes rely on them.
That's only a problem if the inner classes [sic] destructors rely on the Base instance that contains them. In that case either Base should not contain them as members, or their destructor should not depend on Base.
Using this code:
#include <iostream>
class Base
{
public:
class Sub1
{
public:
Sub1()
{
std::cout << "Base::Sub1::Constructed\n";
}
~Sub1()
{
std::cout << "Base::Sub1::Destroyed\n";
}
};
class Sub2
{
public:
Sub2()
{
std::cout << "Base::Sub2::Constructed\n";
}
~Sub2()
{
std::cout << "Base::Sub2::Destroyed\n";
}
};
Sub1 sub1;
Sub2 sub2;
Base()
{
std::cout << "Base::Constructed\n";
}
~Base()
{
std::cout << "Base::Destroyed\n";
}
};
int main()
{
Base base;
}
I get (added comments manually)
> ./a.out
// Build all members first in the order they are declared.
Base::Sub1::Constructed
Base::Sub2::Constructed
// Call the constructor of the object
Base::Constructed
// Destruction happens in revers.
// Calls the destructor code to handle all local resources
Base::Destroyed
// Then destroy all members in reverse order of declaration
Base::Sub2::Destroyed
Base::Sub1::Destroyed
Class members are constructed in a sequence they are defined in class. That means,
class Demonstration
{
XClass x;
YClass y;
};
In above example, x will be constructed before y. As destruction happens in reverse order of construction, y will always be destructed before x.
Okay, so I'm experiencing some very weird issues with storing an array of base class pointers in a class then settings this base class pointers equal to some dynamically allocated derived class pointers.
My code is too long and bloated with GUI calls to post here, so I'll make some mock code here that demonstrates the methodology I'm using
Base Class - Base
class Base
{
public:
Base(){ // do nothing}
virtual void SetUI(){ // do nothing}
}
Derived Class - Derived
class Derived : public Base
{
public:
Derived() : Base() { // do nothing}
virtual void SetUI(){// do nothing}
}
This is a class that basically holds data for my program, it contains an array of pointers to the base class. These pointers are initialized by having them point to dynamically created objects of the derived class type.
class HelperClass
{
private:
Base * basearray[2];
public:
HelperClass()
{
basearray[0] = new Derived;
basearray[1] = new Derived;
}
Base * getBaseArray(int key)
{
return this->basearray[key];
}
}
here is my "main", this is where everything starts getting weird.
int main()
{
HelperClass hold;
hold.getBaseArray(0)->setUI();
// NOTHING HAPPENS ABOVE, THE CODE DOESN'T EVEN REACH THIS POINT, IT JUST GET'S LOST SOMEWHERE IN //THE ABOVE STATEMENT. i KNOW THIS BECAUSE I PUT AN exit(0) inside the function setUI() for both the //base and derived class and the program doesn't exit.
// this also does nothing
if(hold->getBaseArray(0) || !hold->getBaseArray(0))
exit(0);
return 0;
}
but oddly enough, if i do something like the following, where I just declare a base class pointer and have it point to a dynamically created object of the derived class, everything works just fine.
int main()
{
Base *hold;
hold = new Derived;
hold->setUI(); // <- this works polymorphically
return 0;
}
Does anyone have any idea why my program stops working when I try to work with the array of base class pointers inside the HelperClass? When I try to do getBaseArray(int) it doesn't return anything, which causes statements like
if(hold->getBaseArray(0) || !hold->getBaseArray(0)) {exit(0);}
to not make the program exit, which is weird because the pointer that getBaseArray() returns is either null or non-null, which means the program should exit no matter what
I (and my compiler) found two mistackes you have in the first main()
You declare SetUI() in your Base and Derived class, but in the main you try to call setUI(). Perhaps you have both functions in your project and that's why you recieved nothing.
You declare hold as an object and not a pointer. With this you can not do like hold->someFn(). You should call thet like hold.someFn().
Here is the code with corrections. It runs by me without problems. Try it.
struct Base
{
Base(){}
virtual ~Base() {}
virtual void SetUI() {
cout << "base" << endl;
}
};
struct Derived : public Base
{
Derived() : Base() {}
virtual ~Derived() {}
virtual void SetUI() {
cout << "derived" << endl;
}
};
class HelperClass
{
Base * basearray[2];
public:
HelperClass() {
basearray[0] = new Derived;
basearray[1] = new Derived;
}
~HelperClass() {
delete basearray[0];
delete basearray[1];
}
Base *getBaseArray(int key) {
return basearray[key];
}
};
int main()
{
HelperClass hold;
hold.getBaseArray(0)->SetUI();
if(hold.getBaseArray(0))
cout << "some output" << endl;
return 0;
}
please go through my below code:
#include "stdafx.h"
#include <iostream>
#include <conio.h>
using namespace std;
class ClassA
{
protected:
int width, height;
public:
void set_values(int x, int y)
{
width = x;
height = y;
}
virtual int area()
{
return 100;
}
~ClassA()
{
cout << "base class destructor called" << endl;
}
};
class ClassB : public ClassA
{
public :
int area()
{
return (width * height);
}
~ClassB()
{
cout << "derived class destructor called" << endl;
}
};
int main()
{
ClassA *Ptr = new ClassB;
Ptr->set_values(10, 20);
cout << Ptr->area() << endl;
delete Ptr;
return 0;
}
In the above code the pointer contain the address of derived class object so it should call derived class destructor along with base class destructor when i delete the pointer,but why it is calling only base class destructor. if i made base class destructor as virtual then it is calling both derived class and base class destructor why?. and in virtual functions case both the base and derived class has the same function name so compiler resolve the one which is most derived in the derived class but here the destructor won't have same name then how the compiler resolves which one it has to call during run time.please explain me how
You should make the destructor of your base class virtual in order for polymorphic destruction to work properly:
class ClassA
{
// ...
virtual ~ClassA()
// ^^^^^^^
// Add this!
{
cout << "base class destructor called" << endl;
}
};
If you do not do that, you get Undefined Behavior when doing delete Ptr.
if i made base class destructor as virtual then it is calling both derived class and base class destructor why?
This is part of the regular object destruction sequence. When you destroy an object, the destructor of that object's class gets called first, then the destructors of all the non-static class members of that object (in inverse order of declaration), then the destructors of all its base classes.
Thus, virtual dispatch is correctly performed here (if you make your base class destructor virtual, of course), in the sense that the first destructor that gets invoked is the destructor of the actual run-time type of your object (ClassB). After that, the destructor of the base class ClassA gets invoked as well as part of the normal destruction process.
but here the destructor won't have same name then how the compiler resolves which one it has to call during run time
Destructors are special member functions. Each class can have only one destructor, so their name (which must be identical to the name of the class, with the prepended ~ character) is irrelevant. The compiler knows which function is a destructor.
Because your Base class destructor should be virtual.
That's actually undefined behavior because ~ClassA() is not virtual, so anything can happen.
ClassA *Ptr = new ClassB;
///....
delete Ptr;
You need to mark your destructors as virtual. Otherwise the compiler doesn't know to call the most-derived destructor.
virtual ~ClassA()
{
cout << "base class destructor called" << endl;
}
During destruction of the derived class object, i first hit the derived class destructor and then the base class destructor (which is as expected). But i was curious to find out - at what point does the functions of the derived class go out of scope (are destroyed).
Does it happen as soon as the control leaves the derived class destructor and goes toward the base? Or does it happen once we done with the base class destructor also.
Thanks
Once the destructor of the most derived class finishes, the dynamic type of the object can be considered that of the next less-derived-type. That is, a call to a virtual method in the base destructor will find that the final overrider at that point in time is at base level. (The opposite occurs during construction)
struct base {
base() { std::cout << type() << std::endl; }
virtual ~base() { std::cout << type() << std::endl; }
virtual std::string type() const {
return "base";
}
};
struct derived : base {
virtual std::string type() const {
return "derived";
}
};
int main() {
base *p = new derived;
std::cout << p->type() << std::endl;
delete p;
}
// output:
// base
// derived
// base
Functions don't get destroyed.
Virtual functions however get their entry in the v-table erased as soon as the derived destructor finishes so you can't call derived virtual functions from the base d'tor.