问:编写这个类的析构函数的正确和安全的方法是什么?

סטנ*_*ונן 2 c++ qt destructor dynamic dealloc

我在Windows7上使用Qt5,我最近发现了一个有趣的Qt示例代码.

基本上,它看起来像这样:

ButtonWidget::ButtonWidget(const QStringList &texts, QWidget * parent) 
: QWidget(parent)
{
    signalMapper = new QSignalMapper(this);

    QGridLayout * gridLayout = new QGridLayout;
    for (int i = 0; i < texts.size(); ++i) 
    {
        QPushButton * button = new QPushButton(texts[i]);
        connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()));
        signalMapper->setMapping(button, texts[i]);
        gridLayout->addWidget(button, i / 3, i % 3);
    }

    connect(signalMapper, SIGNAL(mapped(QString)), this, SIGNAL(clicked(QString)));

    setLayout(gridLayout);
}
Run Code Online (Sandbox Code Playgroud)

这是一个很好且有用的示例,但它没有正确的析构函数...以防万一我要删除ButtonWidget类型的对象,或者我想自定义代码以便能够删除/添加小部件.这个想法是如何删除在构造函数中创建的所有对象(动态地,使用new).

我的方法是使用私有变量QList<QPushButton*> list,将所有新分配的按钮添加到列表中(在构造函数中),并使用上面的方法在析构函数中逐个删除它们list.但这似乎是幼儿园的方法.

我认为必须有其他方式,更好的方法来做到这一点,没有列表,没有搞乱构造函数代码:)感谢您的时间和耐心!

Wer*_*mus 5

使用接收父作为其构造函数的参数的Qt类,例如QSignalMapper,重要的是要注意该类将其自身添加到其父对象列表中,并且当它的父(一个QObject)被破坏时它将被破坏.

因此,如果您将对象传递给父对象,则不必执行任何操作.您可能在cpp文件中有一个空的析构函数,只是为了确保该成员的定义可用于QObject,但这取决于类.

但是,如果您确实选择编写自己的析构函数,那么正确实现的典型Qt"子"将在销毁时从其父级中删除.

除了标题/标题中提出的问题之外,OP还询问如果他想在删除父项之前删除子对象会发生什么:

瞄准以下内容,似乎(这是我自己的经验),他可能会删除子小部件,并且他们将自行删除.已经提到过,可以将子节点的父节点设置为null,但这不是必需的,除非有人想要删除父节点并使子节点保持活动状态(重新父节点...).

然而,如图中的最后一段例如,实例化的顺序是非常重要的.如果在子节点之后实例化父节点,并且显式设置了子节点的父节点,则子节点将保留指向父节点的死引用/无效指针,并且当子节点尝试从子节点移除时,将发生未定义的行为.超出范围的父母.

除了Qt的文档之外,还可以在这里查看 QObject :: setParent的实现(setParent_helper).由此可以看出,他们付出了巨大的努力,允许儿童/父母的删除没有发生意外,除了上述案例.