【问题标题】:c++ Delete derived from base class like QObject doc ++ Delete从基类派生,如QObject
【发布时间】:2020-03-04 02:56:21
【问题描述】:

我有一个问题。 我怎样才能用析构函数做像 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 类,Derived 类会自行删除。像 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

有点乱。我已经尝试了很多次。

谢谢。

【问题讨论】:

  • 虚拟析构函数?
  • 哦,你谈到了 Qt 所有权抛出父...
  • 错字:virtual ~Person(QDebug() &lt;&lt; "name: " &lt;&lt; name &lt;&lt; "\n";) ?
  • 我使用过虚拟析构函数,但没有像 QT 那样工作。
  • “删除从基类派生的”。这部分是使用虚拟析构函数完成的,但您希望 Qt 的父/子系统拥有所有权。

标签: c++ qt destructor qobject


【解决方案1】:

这不是推导。当你调用这个构造函数时:

Person *Henry{new Person(Cris)};

它将亨利创造为克里斯的孩子。在 Qt 中,每个 QObject 可以有很多孩子。删除父对象时,子对象将被删除。这是通过保留一个子级列表并在调用父级析构函数时删除它们来完成的(在 Qt 中它比这要复杂得多,因为信号/插槽和其他事情也应该被处理)。 您可以通过为您的对象保留一个使用 std 容器的子列表来创建类似的实现。

【讨论】:

  • 感谢您的回答。我刚刚添加了一个我刚刚尝试过的示例。
  • @ChriztHeanvillBigStein,我再说一遍,您使用了误导性名称。这与面向对象和继承无关。这是关于对象的逻辑层次结构。如果在逻辑上有意义,任何对象都可以拥有任何其他对象。
【解决方案2】:

我要在前面说我实际上并没有测试这个,但代码应该是可行的。

我不认为你真的需要额外的Storage 类,这可以直接在Base 类中完成。此外,在Derived 类的构造函数中,您将一个指针传递给指向父级的指针。您只想传递指针本身,否则会出现一些错误,因为您将引用不存在的对象。

另外,我相信您在 Base 类的构造函数中调用 Storage::deleteBase() 函数会删除太多,并过早地使对象无效。这会导致未定义的行为。

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 ) {}
}

【讨论】:

  • 它有效。太感谢了。我曾尝试过这样的方式,但它对删除子项进行了无限循环。
猜你喜欢
  • 1970-01-01
  • 2017-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-21
  • 2013-11-20
相关资源
最近更新 更多