c ++ Удалить производные от базового класса, такие как QObject do - PullRequest
0 голосов
/ 07 ноября 2019

У меня есть вопрос. Как я могу сделать что-то вроде QObject с деструкторами?

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;
}

Выход:

name: Cris.
name: Henry.

Я хочу удалить только класс Base ,и производные классы будут удалены самостоятельно. Как QT, но без QT.


Отредактировано: Это мой пример кода:

#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

Это немного грязно. Я много раз пробовал со многими тестами.

Спасибо.

Ответы [ 2 ]

2 голосов
/ 07 ноября 2019

Я собираюсь префикс этого, говоря, что я на самом деле не тестировал это, но код должен быть работоспособным.

Я не думаю, что вам действительно нужен дополнительный класс Storage, это можетпросто сделайте это прямо в классе Base. Далее, в конструкторе класса Derived вы передаете указатель на указатель на родителя. Вам нужно только передать сам указатель, иначе вы получите некоторые ошибки, так как будете ссылаться на объекты, которые не существуют.

Кроме того, я считаю, что ваш вызов в конструкторе класса Base к *Функция 1009 * удалит слишком много и сделает объекты недействительными преждевременно. Это может привести к неопределенному поведению.

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 ) {}
}
1 голос
/ 07 ноября 2019

Дело не в получении. Когда вы вызываете этот конструктор:

Person *Henry{new Person(Cris)};

, он создает Генри как дитя Криса. В Qt у каждого QObject может быть много детей. Дочерний объект будет удален при удалении родителя. Это делается путем сохранения списка потомков и удаления их при вызове родительского деструктора (это гораздо сложнее, чем это в Qt, так как сигнал / слоты и другие вещи также должны обрабатываться). Вы можете создать аналогичную реализацию, сохранив список дочерних элементов, использующих контейнеры std для ваших объектов.

...