I have a question. How I can do something like QObject do with the Destructors?
Class Person : public QObject{
//...
public:
Person(QObject *p = nullptr) : QObject(p){}
virtual ~Person() { QDebug() << "name: " << name << "\n";}
// Getters, Setters
};
int main(int argc, char* argv[]){
QCoreApplication a(argc, argv);
Person *Cris{new Person};
Person *Henry{new Person(Cris)};
Cris->setName("Cris");
Henry->setName("Henry");
delete Cris;
}
The out put is:
name: Cris.
name: Henry.
I want to delete just the Base class, and the Derived classes will be deleted by themselves. Like QT do, but without QT.
Edited: This is my code example:
#include <iomanip>
#include <iostream>
#include <list>
#include <memory>
#include <string>
#include <vector>
using namespace std;
class Base;
class Derived;
class Storage {
public:
static void addBase(Base **b) { l_base.push_back(*b); }
static void printBase() {
std::cout << "\n // ------------------------------------ // \n";
for (auto *fl : l_base) {
cout << fl << endl;
}
}
static void deleteBase() {
std::cout << "\n // ------------------------------------ // \n";
// for (auto *fl : l_base) {
// // Derived *dd = reinterpret_cast<Derived *>(fl);
// cout << l_base.front() << endl;
// cout << l_base.back() << endl;
// delete l_base.back();
// l_base.pop_back();
// }
auto d = l_base.front();
while (!l_base.empty()) {
if (d != l_base.front()) {
delete l_base.back();
l_base.pop_back();
} else {
l_base.pop_front();
}
}
// l_base.clear();
cout << "\nCleared.\n";
}
private:
// Base *bp;
static list<Base *> l_base;
};
class Base {
friend class Storage;
protected:
public:
Base(Base **b = nullptr, string n = "") {
if (n == "") {
name = "Empty";
} else {
name = n;
}
if (b != nullptr) {
// bp = b;
bp = this;
Storage::addBase(&bp);
Storage::printBase();
}
std::cout << "\n Base Constructor.\n "
<< "And names: " << name << "\n";
} // Constructor
virtual ~Base() { //
Storage::deleteBase();
} // Destructor
bool operator==(Base *b) {
if (this == b) {
return true;
}
return false;
}
bool operator!=(Base *b) { return !(this == b); }
private:
Base *bp;
// Derived *dp;
string name;
// static _init s_init;
}; // Base
class Derived : public Base {
private:
string name;
protected:
public:
Derived(Base *b = nullptr, const string n = "") //
: Base(&b, n), name(n) {
std::cout << "\n Derived Constructor.\n ";
// << "Show Address: " << b << "\n";
} // Constructor
virtual ~Derived() {
std::cout << "\n // ------------------------------------ // \n";
std::cout << "\n // ------------------------------------ // \n";
std::cout << "\n // ------------------------------------ // \n";
std::cout << "\n // ------------------------------------ // \n";
std::cout << "\n // ------------------------------------ // \n";
std::cout << "\n // ------------------------------------ // \n";
std::cout << "\n Derived ------- Destructor.\n "
<< "name: " << name;
} // Destructor
void derived_dSome() { std::cout << "\n Derived_dSome.\n "; }
}; // Derived
// Static
list<Base *> Storage::l_base;
// Base::_init Base::s_init;
/* Main */
int main(int argc, char const *argv[]) {
Derived *a{new Derived};
Derived *b{new Derived(a, "Second")};
Derived *c{new Derived(a, "Third")};
cout << "\n\n ================== List of Derived: ==============="
<< "\na: " << a << "\nb: " << b << "\nc: " << c;
delete a;
// delete d;
std::cout << "\n\n---------------------"
<< "\n End of the program.\n"
<< "---------------------\n";
return 0; // Ending program
} // Main
It is a little messy. I had tried many times with many test.
Thank you.
I'm going to prefix this by saying I didn't actually test this, but the code should be workable.
I don't think you really need the extra Storage
class, this can simply be done directly in the Base
class instead. Further, in the Derived
class's constructor, you are passing a pointer to a pointer to the parent. You only want to pass the pointer itself, otherwise you will be getting some errors, as you will be referencing objects which do not exist.
Also, I believe your call in the Base
class's constructor to the Storage::deleteBase()
function will delete too much, and invalidate objects prematurely. This would then lead to undefined behaviour.
class Base {
public:
Base( Base *parent = nullptr ) {
if ( parent )
parent->addChild( this );
}
virtual ~Base() {
for ( Base *child : children )
delete child;
}
private:
void addChild( Base *child ) {
children.push_back( child );
}
std::vector<Base*> children;
};
class Derived : public Base {
public:
Derived( Base *parent = nullptr ) : Base( parent ) {}
}
It's not about deriving. When you are calling this constructor:
Person *Henry{new Person(Cris)};
it creates Henry as a child of Cris. In Qt, each QObject can have many children. Child object will be deleted when the parent is deleted. This is done by keeping a list of children and deleting them when the parent destructor is called (it's a quite more complex than this in Qt as signal/slots and other things should be handled as well). You can create a similar implementation by keeping a list of children using std containers for your objects.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.