Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C+中调用析构函数之前执行操作+;QObject子类_C++_Qt_Inheritance - Fatal编程技术网

C++ 在C+中调用析构函数之前执行操作+;QObject子类

C++ 在C+中调用析构函数之前执行操作+;QObject子类,c++,qt,inheritance,C++,Qt,Inheritance,我有一个继承QObject的类层次结构 我需要在构建之后(当对象完全构建时)和销毁之前(当对象仍然完整时)执行一些操作 构造部分没有问题,因为我可以控制对象的构造,将其构造函数私有化,并将已经可以执行所有所需操作的creator函数公开 问题来自于析构函数。我做了大致相同的事情:隐藏析构函数并提供一个destructor函数,该函数执行所有操作,然后销毁对象 问题从这里开始:我的类层次结构被用作QJSEngine脚本模块的一部分,该模块拥有所有对象的所有权,到了时候,它会使用QObject的析构

我有一个继承QObject的类层次结构

我需要在构建之后(当对象完全构建时)和销毁之前(当对象仍然完整时)执行一些操作

构造部分没有问题,因为我可以控制对象的构造,将其构造函数私有化,并将已经可以执行所有所需操作的creator函数公开

问题来自于析构函数。我做了大致相同的事情:隐藏析构函数并提供一个destructor函数,该函数执行所有操作,然后销毁对象

问题从这里开始:我的类层次结构被用作QJSEngine脚本模块的一部分,该模块拥有所有对象的所有权,到了时候,它会使用QObject的析构函数销毁它们,从而绕过我的析构函数。声明我的析构函数为私有是没有帮助的,因为QJSEngine总是可以执行QObject的析构函数(顺便说一句,也可以执行将我的指针投射到QObject的任何代码段)

我需要在调用析构函数之前执行此操作,因为我使用了一些虚拟函数,所以我需要在开始销毁过程之前执行此操作,以便虚拟函数调用不会失败

有没有办法做到这一点

我附上一个基本代码,显示我的问题:

class IBase: public QObject {
public:
    template<typename T>
    static IBase * create() {
        IBase * obj=new T;
        obj->afterConstruction();
        return obj;
    }

    void destroy() {
        this->beforeDestruction();
        delete this;
    }

protected:
    IBase(): fBeforeDestruction(false){}
    virtual ~IBase(){
        //Try to perform operations, but it is too late....
        if (!fBeforeDestruction)
            doBeforeDestruction();
    }

    virtual void doAfterConstruction(){}
    virtual void doBeforeDestruction(){}
private:
    bool fBeforeDestruction;
    void afterConstruction() {
        doAfterConstruction();
    }

    void beforeDestruction(){
        fBeforeDestruction=true;
        doBeforeDestruction();
    }
};

class TSubclass: public IBase {
protected:
    TSubclass(){}
    virtual ~TSubclass(){}

    virtual void doAfterConstruction(){
        qDebug()<<"AfterConstruction";
    }
    virtual void doBeforeDestruction(){
        qDebug()<<"BeforeDestruction";
    }
private:
    friend class IBase;
};

int main(int argc, char *argv[])
{
    //QObject *obj=new TSubclass() //Compile time error! Nice!
    QObject *obj=IBase::create<TSubclass>();

    delete obj;//Wrong! BeforeDestruction is NEVER shown!!! <---- How to change this behaviour?

    IBase * obj2=IBase::create<TSubclass>();
    //delete obj2;    //Compile time error! Nice!
    obj2->destroy();  //Nice!
}
类IBase:公共QObject{
公众:
样板
静态IBase*create(){
IBase*obj=新T;
obj->后结构();
返回obj;
}
无效销毁(){
这->在销毁之前();
删除此项;
}
受保护的:
IBase():fBeforeDestruction(false){}
虚拟~IBase(){
//尝试执行操作,但为时已晚。。。。
如果(!fBeforeDestruction)
dobefordestruction();
}
虚拟void doAfterConstruction(){}
虚拟void doBeforeDestruction(){}
私人:
布尔重构;
施工后无效(){
doAfterConstruction();
}
销毁前无效(){
fBeforeDestruction=真;
dobefordestruction();
}
};
TSubclass类:公共IBase{
受保护的:
TSubclass(){}
虚拟~TSubclass(){}
虚拟构造(){

首先,我必须说,从构造函数或析构函数调用虚方法是非常困难的

  • 从IBase的mose派生后代的构造函数调用
    doAfterConstruction()
  • 从IBase的mose派生后代的析构函数调用
    doBeforeDestruction()
  • 您可以使用信号/插槽执行相同操作:

  • IBase
    中声明一个信号
    beforedemployed()
    (同时添加Q_对象宏)
  • IBase
    的构造函数中,将此信号连接到插槽
    dobefordestruction
    (使其成为插槽)
  • 在IBase的mose派生子代的析构函数中,发出信号:
    emit beforedemployed()
  • 如果您有很多子体,您可能希望避免在每个构造函数/析构函数中执行相同的操作。在这种情况下,您还可以使用模板:

    template <class T>
    class FirstAndLastCall : public T
    {
    public:
      FirstAndLastCall ()
      {
        doAfterConstruction();
      }
      ~FirstAndLastCall 
      {
        doBeforeDestruction();
      }
    }
    
    Usage:
    
    IBase* obj2 = new FirstAndLastCall<TSubclass>();
    
    模板
    类First和LastCall:公共T
    {
    公众:
    FirstAndLastCall()
    {
    doAfterConstruction();
    }
    ~z~第一个和最后一个电话
    {
    dobefordestruction();
    }
    }
    用法:
    IBase*obj2=新的FirstAndLastCall();
    
    类中缺少Q_OBJECT宏,为什么还要隐藏析构函数?这里不需要Q_对象,因为没有信号/插槽/属性。您声明需要在销毁之前“当对象仍然完成”执行操作-为什么不能在析构函数本身中执行这些操作?在退出析构函数之前,对象仍然是“完整的”。尽管描述很长,但我仍然不明白为什么不能将销毁代码放在析构函数中,比如说放在析构函数中。@Merlin069和C.R。我不能将代码放在析构函数中,原因有两个:虚拟调用是在析构函数本身中调用ing(它不会执行我想要的操作,因为它不会调用重写的函数)因为我做了几次动态_强制转换,在析构函数中失败了。我更新了我的问题,我知道我不能从构造函数/析构函数调用虚拟方法。否则我不会问…你使用FirstAndLastCall模板的方法非常有趣,因为从最派生的析构函数,动态_强制转换(请参阅我的问题更新)成功。我将稍后再评论
    template <class T>
    class FirstAndLastCall : public T
    {
    public:
      FirstAndLastCall ()
      {
        doAfterConstruction();
      }
      ~FirstAndLastCall 
      {
        doBeforeDestruction();
      }
    }
    
    Usage:
    
    IBase* obj2 = new FirstAndLastCall<TSubclass>();