1

I've realized today that if you have 3 classes like so:

class 1 has a signal

class 2 has a signal that connects to class 3's private slot

class 3 has a private slot and class 2 is a friend of class 3

If I connect class 1's signal to class 2's signal, I can essentially call class 3's private slot by emitting class 1's signal.

If signals were private or protected this wouldn't occur.

There's another scenario where this can be bad, imagine we have this setup:

class 1 has a signal

class 2 has a signal that connects into it's base classes protected slot

class 3 is the base class with a protected slot

Doesn't this break Object Oriented Principles?

  • 1
    Friend classes tend to break "object oriented principles" – Kevin Apr 23 '19 at 21:05
  • @Kevin what about having a base class in the second scenario – JComputerScience Apr 23 '19 at 21:06
  • Protected fields (slots, data members, etc) can do the same thing. Class 2 can do whatever it wants to protected things it inherits. It's more a "problem" with public/protected/private interfaces than with signals/slots specifically. I'm not familiar with Qt so I can't answer to the design choices made there, but as C++ is a multi-paradigm language you can break OOP when you feel like it. – Kevin Apr 23 '19 at 21:11
  • @Kevin I have a class that emits signals to call slots that I want no one to be able to call ever. However since signals are public, a developer can make their own class and connect any instance of their class with an instance of my class to call functions that were never meant to be called by any class but the one emitting the original signal. Since these signals give gate ways to access functions developers shouldn't have access to I have no way to secure my code unless I use round about ways of calling these slots. – JComputerScience Apr 23 '19 at 21:16
  • 2
    You can't use C++ private/public mechanism to secure your code anyway. Why would you want to? If the attacker has such access to your code, they can do anything anyway. But, look up PIMPL idiom, which is extensively used by Qt library itself to hid Private IMPLementation (to allow keeping binary compatibility between minor versions of the library, in Qt's case). – hyde Apr 23 '19 at 21:43
  • 1
    Also, if you're worried about others doing things you don't want to allow, you might want to checkout Qt meta object system... It allows QObject class introspection/reflection, and you can call any invokable methods (signals, slots and Q_INVOKABLE marked methods) and access properties and find out the QObject parent-child hierarchy tree. – hyde Apr 23 '19 at 21:48

1 Answers1

5

woboq mentions this:

Signals were protected in Qt4 and before. They are becoming public in Qt5 in order to enable the new syntax.


You can create a private / protected helper object with the 'private' signal:

class Helper : public QObject
{
    Q_OBJECT
public:
    Helper(QObject *parent) : QObject(parent) { }
signals:
    void MyPrivateSignal();
};

class MyClass : public QObject
{
    Q_OBJECT
public:
    MyClass()
        : QObject(),
        helper(new Helper(this))
    {
        connect(helper, &Helper::MyPrivateSignal, this, &MyClass::MyPrivateSlot);
    }

private slots:
    void MyPrivateSlot();

private:
    void InvokeMyPrivateSignal()
    {
        emit helper->MyPrivateSignal();
    }

private: // or protected:
    Helper *helper;
};

Anyone can connect to Helper::MyPrivateSignal() of a Helper instance, but not to your Helper instance, because only you know that one.

Martin Hennings
  • 16,418
  • 9
  • 48
  • 68