How to make a constructor like QObject?

4

Having a new question about an old question, I want to know how to create a class equal to QObject . Basically, I want to know:

  • How to make a copy constructor that does not accept assignment operators?
  • How to make a class that can delete others?
  • How to make a class similar to QObject ?
asked by anonymous 12.02.2014 / 18:16

2 answers

6

The QObject of Qt were designed to work in the heap without so much difficulty with memory handling. They are non copiable (private or deleted copy constructor). In addition each object can have a relative will have zero or more children. Setting the relative of an object means adding to the parent's list of children. The destroyer of each object deletes all children. Note that if an object is created outside the heap, it is not recommended that it has a relative, since it will attempt to call delete on the child in its destructor.

The implementation is similar to this:

#include <algorithm>
#include <vector>

class Object {
    std::vector<Object*> _children; // No QObject é usado um QList aqui
    Object* _parent = nullptr;
public:
    Object(Object* parent=nullptr) { setParent(parent); }
    Object(const Object&) = delete;

    void setParent(Object* parent) {
        if (_parent) {
            std::vector<Object*>& vec = _parent->_children;
            vec.erase(std::remove(vec.begin(), vec.end(), this), vec.end()); // remove this
        }
        _parent = parent;
        if (_parent) {
            _parent->_children.push_back(this);
        }
    }

    virtual ~Object() { // destrutor deve ser virtual, já que é uma base abstrata
        setParent(nullptr); // Se remove do seu parente
        for (Object* child : _children)
            delete child; // deleta todos os filhos e, por recursão, seus filhos
    }
};
    
12.02.2014 / 18:25
3

QObject has a list of children within it. Something like:

class QObject {
  std::vector<QObject*> children;
  QObject *parent;
};

The constructor basically saves the parent and adds the object to your list

QObjec(QObject *parent) : parent(parent) {      
  if (parent)
    parent->children.push_back(this);
} 

The magic stays in the destructor. He has to destroy all the children. That's easy. But he has to care if he is someone's child, he needs to remove himself from his list to avoid a% double.

virtual ~QObject() {
  if (parent) 
    parent->removeChild(this);

  for (unsigned i=0; i<children.size(); ++i) {
    delete children[i];
  }
}

The destructor must be virtual, because at the time of invoking it we want to be called the destructor of the correct class, and only the one of QObject. To remove yourself from the parent list, something like this could be done:

QObject::removeChild(QObject *child) {
  std::vector<QObject*>::iterator iter = std::remove(children.begin(), children.end(), child);
  children.erase(iter, children.end());
}

I just did not really understand what you meant by builder that does not accept assignments.

    
12.02.2014 / 18:28