3

Hi, all... I'm working with Qt not for a long time, but recently a thought came to my mind. QObject has public function children() and a few other ones, which return pointer to a child object(s). So any client of custom class can break encapsulation.

  1. How can I protect my code from such barbaric treatment?

  2. Why did Qt developers leave such functionality in public section? What purpose did they try to achieve?

The only one argument about such functions I can imagine is connected with 'garbage collection' in Qt (when one delete parent QObject derived class instance all children instances are automatically deleted). But I think it could be done with Qt's metaObject system (I'm not sure in the mechanism, however, access to child objets shouldn't be public, on my opinion).

  1. Also, consider situation when someone attempts to use child object in separate thread, which is forbidden in Qt... but I don't see any restrictions in light of using QObject::children().

//------------------------------------------------------------------------------------------------

further explanation according to some comments:

While you have access with QObject::children() to private members of the class, e.g.

class MyClass: public QWidget{ private: QLabel* m_lbl1; };
...
MyClass* p = new MyClass;
QLabel* pLbl = p->findChild<QLabel>();

there is no need to declare member m_lbl1 as private one:

class MyClass: public QWidget{ public: QLabel* m_lbl1; };

and it's very bad. because if you have at least 10^5 lines of code in your solution and more that 1 developer, sooner or later someone can manually change state of any child member of MyClass and you can achieve any kind of bug (e.g. behavior which is not possible according to MyClass implementation).

@Merlin069: is pImpl a common approach in Qt's development?

Illia Levandovskyi
  • 1,228
  • 1
  • 11
  • 20
  • I believe this is part of [Qt's Object Trees](http://qt-project.org/doc/qt-4.8/objecttrees.html) architecture, which I personally find quite clever. I don't understand what you mean by "break encapsulation" or "protect your code from such treatment". Can you please elaborate? What "treatment" are you worried about? Please note that Qt is built on C++, which is not a "managed" language, so it's up to you to make sure that your code isn't treating anything "barbarically". – deGoot May 08 '14 at 22:56

1 Answers1

3

The Qt object's parent system is very useful, but I think I understand what you're getting it.

For example, assuming all objects declared here are derived from QObject:-

class MyClass : public QObject
{
    Q_OBJECT

    private:
        SomeOtherClass* m_pOtherClass = nullptr; // C++ 11 initialisation
};

In the constructor of MyClass...

m_pOtherClass = new SomeOtherClass(this);

So, we now have the encapsulated SomeOtherClass object, but as it's parent is MyClass, it's also accessible via the function children() from MyClass.

If you want encapsulation here, then you can sacrifice using the parent / child hierarchy and declare SomeOtherClass with a NULL parent.

However, if you consider the reason for Qt's Object Trees, as @deGoot mentions, then it provides such a useful system whose benefits outweigh breaking the encapsulation.

Now, if we really want to maintain encapsulation and use the QObject parenting system we can do so by using a Private Implementation (pimpl), which you can read about here. Also, internally, Qt uses this too.

TheDarkKnight
  • 27,181
  • 6
  • 55
  • 85
  • 1
    I've been finding that pimpl is the best way to achieve encapsulation in C++. If you "expose" your class's private members in a header file, someone can always break encapsulation using pointer manipulation. – deGoot May 09 '14 at 13:54
  • 1
    Pimpl is *heavily* used by Qt. If you look at their source code (it is opensource after all), you will see that most private data is hidden in private objects which are referenced in the "public" object. – deGoot May 09 '14 at 13:58