#include <iostream>
using namespace std;
class Abstract {
protected:
int* arr;
int size;
public:
Abstract(int s = 10)
{
size = s;
arr = new int[size];
}
virtual ~Abstract()
{
if (arr)
{
delete[] arr;
}
arr = nullptr;
}
virtual void foo() = 0;
void func() { foo(); }
};
class Derived : public Abstract
{
public:
void newArr()
{
Abstract::~Abstract(); // <=> this->~Derived()
arr = new int[size];
}
virtual void foo()override {};
};
int main() {
Derived d;
d.func();//ok
d.newArr();//ok
d.func();//error
return 0;
}
After calling distractor of abstract class, and setting new values to arr from derived class, next time abstract class use pure virtual function foo, it won't redirect to derived override implementation, and get debug abort() error.
As stated in documentation
Though sometimes it can be called explicitly, those cases are extremely rare and quite complex. Your code express multiple cases of Undefined Behavior due to calling a method of destructed object and calling destructor twice:
(emphasis is mine)
So simple solution is to have ordinary method, probably protected in your case, which deallocates the array and call it from the destructor and your function:
and then use the same function in the derived class. For cleaner code I would also add protected method
void allocate( size_t size )and move membersarrandsizeto private area of the base class.Note: I assume you are doing this exercise to better understand how things work in C++ so I answered accordingly. In real code though raw pointers owning memory should be avoided in favor of smart pointers or proper containers to eliminate many potential problems in your code (for example your class is violating The rule of three/five/zero).