简体   繁体   中英

c++ Delete derived from base class like QObject do

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM