0

I am implementing a class Exporter to perform some export actions. This class derives from QObject. I want to create a pointer to that class on the heap from a const function of the class C (C::triggerExport). I cannot create a unique_ptr as a member of the class C, since I cannot modify it from the triggerExport member.

class Exporter
{
   void export()
   {
      // Do some initialization.... 
      // problem: if an exception is thrown here, the Exporter will never
      // be deleted
      QDialog * dialog = new QDialog();
      connect(dialog, SIGNAL(rejected()), SLOT(deleteLater());
   }
};

class C
{
  void triggerExport() const
  {
     //create new here
     Exporter * e = new Exporter;
     e->export();
  }
};

How can I design Exporter in a way that won't cause leaks in the presence of exceptions?

Llopeth
  • 406
  • 5
  • 11

3 Answers3

0

Since you do not return the Exporter pointer from triggerExport, there is not much you have to take care of.

An object is allowed to delete itself in C++. So as long as you don't perform any operations on members after that, you can just call delete this; when done.

Using deleteLater() is possible too, only that the object will not be destroyed before the the event loop runs again. And Exporter would have to derive from QObject for that.

If decided to derive Exporter from QWidget, you could just set the Qt::WA_DeleteOnClose flag and Qt would take care of the destruction after the widget has been closed.

SteakOverflow
  • 1,953
  • 13
  • 26
  • It does derive from QWidget but two issues still remain: 1) if Exporter::export() never gets called, it will never be deleted 2) if for some reason, an exception is thrown the code might be interrupted, so the problem is not that we have to call deleteLater, but how to do it in a safe way (making sure that it gets called) in this case – Llopeth Apr 25 '18 at 11:59
  • Well this answers the question you asked. For circumstances so very different you will have to describe them with much more detail (with code), preferably in a separate question. – SteakOverflow Apr 25 '18 at 12:55
0

If I have understood that correctly, check the solution below:

class Exporter:public QDialog
    {
      signals:
        void closeDialog();
      protected:
         void closeEvent(QCloseEvent *event)
         {
          emit closeDialog();
          event->accept();
        } 

       void export()
       {
           //Do the stuff
       }
    };

    class C
    {
      Exporter * e=0;
     public slots:
       void deleteExporter()
         {delete e;
           e=0;
          }
      void triggerExport() 
      {
          if(e){return;}
         //create new here
         e = new Exporter;
         connect(Exporter,SIGNAL(closeDialog()),this,SLOT(deleteExporter()));
         e->export();
      }



    };
Veera
  • 331
  • 3
  • 15
  • That code won't compile because you are trying to modify the non-static const member "e" from a const method (triggerExport) , which is precisely the difficulty of this question – Llopeth Apr 25 '18 at 13:42
  • Do you need the function to be const? – Veera Apr 25 '18 at 14:11
0

I cannot create a unique_ptr as a member of the class C, since I cannot modify it from the triggerExport member.

Actually, you can, using unique_ptr::reset()

Assuming C contains something like this:

class C {
...
    void triggerExport();
private:
    std::unique_ptr<Exporter> exporter;
};

Then you can write triggerExport() like this:

void C::triggerExport() {
    exporter.reset(new Exporter);
    exporter->export();
}
Aurélien Gâteau
  • 4,010
  • 3
  • 25
  • 30