SoFunction
Updated on 2025-03-04

Examples of several code writing methods for connect in Qt C++

Preface

thisconnectFunctions are like the word "fen" in the programming world, with ever-changing changes and unique advantages. As for us programmers, just like Kong Yiji, although sometimes they find these changes a little funny and even a bit troublesome, after all, they have to learn and use them obediently. After all, this is a "must-have skill" in programming. Everyone has their own habits and characteristics when writing connect. We need to go into it in depth.

In Qt,connectFunctions are used to connect signals to slots so that slot functions are automatically called when signals are transmitted. Qt offers several different types ofconnectThe writing method and the way to define slot functions have their own characteristics and applicable scenarios.

1. Traditional slot function writing

In traditional Qt projects, slot functions are usually used in class header filesslots:A special member function declared by a keyword. For example:

class MainWindow : public QMainWindow {
  Q_OBJECT
 
public:
  MainWindow(QWidget *parent = nullptr);
  ~MainWindow();
 
private slots: // Declare slot functions using slots keyword  void onCalculateClicked();
 
  // ... Other members and slot functions ...};

Then implement this slot function in the source file:

void MainWindow::onCalculateClicked() {
  // Implementation of slot functions}

When using this writing method,conectFunctions are usually called like this:

connect(pbt, SIGNAL(clicked()), this, SLOT(onCalculateClicked()));

The one used here isSIGNAL()andSLOT() macroto convert signals and slots into identifiers in string form.

2. Connect writing using function pointer (5.0)

In 5.0 and subsequent Qt versions, it is recommended to use function pointersconnectWritten because it provides better type checking and compile-time error detection. This writing method does not require useslots:Keyword orSIGNAL()/SLOT()Macro, instead, use function pointers directly. For example:

connect(pbt, &QPushButton::clicked, this, &MainWindow::onCalculateClicked);

In this way of writing,&QPushButton::clickedIt's a signalclickedfunction pointer,&MainWindow::onCalculateClickedis a function pointer to the slot function. The compiler checks whether these pointers match at compile time. The advantages of this writing are as follows:

  • Type safety
    Function pointerconnectWriting provides compile-time type checking. This means that if the signal and slot's function signature do not match, or the specified function does not exist, the compiler will immediately give an error message. This greatly reduces the possibility of runtime errors, as all connections are verified at compile time.

  • Easy to read and maintain
    Using function pointers makes the code more intuitive and easy to understand. You can directly see which signal is connected to which slot, without indirect representation via strings. This helps with code maintenance and debugging, as you can more easily track the connection relationship between signals and slots.

  • Automatically handle function overloading
    When there are multiple overloaded signals or slot functions, the correct overloaded version can be automatically selected using the function pointer. TraditionalSIGNAL()andSLOT()Macros may encounter problems when dealing with overloaded functions because they rely on string representations of function names and cannot distinguish overloaded functions. The function pointer contains the complete signature of the function, so you can accurately select the desired function.

  • Improve performance
    Although the performance difference may not be very significant, the function pointerconnectIt may be written slightly faster than a macro using strings. This is because function pointers can be parsed and concatenated directly at compile time without string comparison and searching at runtime.

  • Compatible with modern C++ standards
    With the continuous development of C++ standards, the use of function pointersconnectThe writing style is more in line with the programming style of modern C++. It takes advantage of features in C++11 and later, such as lambda expressions and smart pointers, allowing Qt's code to be better integrated with these modern features.

  • Reduce the use of macros
    Reducing the use of macros can reduce the complexity of the code and potential errors. Macros are often the source of problems that are difficult to debug in C++ because they are unfolded in the preprocessing phase, rather than type checking during the compilation phase. Using function pointers can avoid these problems.

3. Lambda expression as slot function (C++11)

After C++11, in addition to traditional slot functions and function pointers, Qt also supports the use of Lambda expressions as slot functions. This writing is very flexible because it allows you toconnectThe code for the slot function is written directly in the call, without defining additional member functions in the class. For example:

connect(pbt, &QPushButton::clicked, this, [this]() {
  // Implementation of Lambda expression as slot function  bool isOK;
  double r = lEdit->text().toDouble(&isOK);
  if (isOK && r >= 0) {
    lab2->setText(QString::number(AreaCircal(r)));
  } else {
    lab2->setText("Please enter a legal radius!");
  }
});

The advantages of this writing are as follows:

  • Capture or reference capture to control the life cycle and scope of these variables.

  • Flexibility and dynamics
    Lambda expressions provide a flexible way to define the behavior of slot functions. You canconnectWrite Lambda expressions directly in the call without declaring slot functions in the class in advance. This allows you to dynamically define the behavior of slot functions at runtime as needed.

  • Reduce the code volume
    Using Lambda expressions as slot functions can reduce the amount of code that needs to be written. You don't need to declare a member function for each slot function, which not only reduces the amount of code, but also makes the code more compact and manageable.

  • Type safety
    Using Lambda expressions as slot functions provides better type safety compared to traditional string macros. The compiler checks at compile time whether the type of the Lambda expression matches the parameter type of the signal, thus avoiding runtime errors.

In addition to the first traditional writing method, the two or three more popular writing methods are compared and analyzed as follows:

characteristic Lambda Expressions Function pointer
Introduce time C++11 Early C++ versions, Qt5.0
How to define Anonymous functions are defined directly in the code The function needs to be declared and defined explicitly, and then point to the function through the function pointer
Syntax conciseness Concise, directly defined at the call Relatively cumbersome, requiring additional function declarations and definitions
Type inference Supported, the compiler can infer types based on context Not supported, need to explicitly specify the function return type and parameter type
Capture external variables Can capture variables in external scope Unable to directly capture external variables, only access function parameters
Execution Environment Execute in new stack frames with independent call environment and stack space Point to existing functions and do not have independent stack space
flexibility Suitable for simple, single-line expressions, easy to implement functional closures at the time and place required Suitable for calling already defined functions, supporting dynamic binding and callback functions
Code reusability Usually used for one-time or short-term function definitions, with less reusable code The same function can be called at different locations through function pointers, and the code is highly reusable.
Type safety Type-safe, compiler checks function signature Low type safety, easy to cause type mismatch
performance Performance losses after optimization of modern compilers are negligible, but in some cases it can lead to slight overhead Usually the performance overhead is low, but indirect calls may bring some additional overhead
Use scenarios Suitable for scenarios where simple anonymous functions need to be defined, such as sorting and filtering in STL algorithms Suitable for scenarios where different functions are required to dynamically call different functions or implement callback functions, such as event processing, plug-in systems, etc.

A summary of the characteristics and differences of the above three methods:

  • Traditional slot functions: Easy to read and maintain, especially when the slot function logic is complex or requires multiple reuse. However, they increase the complexity of the class because slot functions need to be declared in the header file.
  • Connect function pointer: Provides better type safety and reduces the possibility of runtime errors. It is the recommended way of modern Qt programming.
  • Lambda Expressions: Very flexible, suitable for simple, one-time slot function logic. However, if Lambda expressions are too complex, it may reduce the readability of the code.

4. Use QOverload to select the writing method of overloaded signals (Qt5.7)

useQOverloadThe writing method of selecting overloaded signals was also introduced in Qt5, which has significant advantages in the Qt framework and is suitable for specific scenarios. For example, when using comboBox, sometimes indexes are used, and sometimes strings are used as parameters:

    QComboBox *comboBox = new QComboBox;
    QLabel *label = new QLabel;
    label->setText("Initial Text");
 
    // Add some options to the combo box    comboBox->addItem("Option 1");
    comboBox->addItem("Option 2");
    comboBox->addItem("Option 3");

    // Use QOverload to connect the overloaded signal to different slots    QObject::connect(comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
                     [](int index){ qDebug() << "Current index changes:" << index; });
 
    QObject::connect(comboBox, QOverload<const QString&>::of(&QComboBox::currentIndexChanged),
                     [](const QString &text){ qDebug() << "Current text changes:" << text; });

In this example,currentIndexChangedThe signal is overloaded twice: one accepts an integer parameter (representing the index of the currently selected item) and one accepts a string parameter (representing the text of the currently selected item). We useQOverloadThe template class specifies which overloaded version of the signal we want to connect to. We then use a lambda expression to define the code that is executed when the signal is emitted.QOverloadis a template class introduced in Qt 5.7 and later, which is used to provide type safety when connecting reloaded signals. In versions prior to Qt 5.7, you may need to usestatic_castor function pointers to implement the same function, but doing so is usually less secure and error-prone.

Specific advantages:

  • Type safety
    • useQOverloadIt is ensured that when connecting signals and slots, the parameter types of signals and slots exactly match. This helps catch potential errors at compile time and improves code stability.
  • Clear and clear
    • The code is clearer and easier to understand by explicitly specifying the version of the overloaded signal to be connected. Other developers can see the correspondence between signals and slots at a glance, reducing misunderstandings and errors.
  • flexibility
    • QOverloadAllows developers to select the signal version that best suits the current needs to connect when there are multiple reloaded versions of the signal. This increases the flexibility of the code, allowing it to adapt to different scenarios and needs.
  • Avoid ambiguity
    • In noQOverloadPreviously, if there were multiple overloaded versions of the signal, developers would need to specify the version of the signal to be connected through other ways (such as function pointer conversion), which could introduce ambiguity and errors. andQOverloadA direct and clear way to avoid these problems is provided.

This writing method is used when there are multiple overloaded versions of the signal,QOverloadThe template class explicitly specifies which overloaded version of the signal to be connected. For example, comboBox::currentIndexChangedThe signal may have multiple reloaded versions, and by usingQOverload<int> or QOverload<const QString&>Identify it and then process it. Adapt to scenarios:

  • There are multiple reloaded versions of the signal
    • When there are multiple overloaded versions of signals in the class, useQOverloadYou can explicitly specify the overloaded signal version to connect to, thereby avoiding connection errors or ambiguity.
  • Type-safe signal slot connection is required
    • In projects with high type safety requirements, useQOverloadIt can ensure that the parameter types of signals and slots are exactly matched, reducing the possibility of runtime errors.
  • Complex GUI applications
    • In complex GUI applications, the connection between signals and slots can become very complex. useQOverloadIt can make the code clearer and easier to understand, and facilitate maintenance and management.
  • Requires flexibility in handling different parameter types
    • In some scenarios, it may be necessary to process signals based on different parameter types. useQOverloadSignal versions of different parameter types can be easily selected to connect to meet these needs.

Having written this, I feel that it is a bit similar to the several ways of writing the word "Jade" mentioned by Kong Yiji. Here is the QtconnectFunctions are simply the word "fen" in the programming world! If Kong Yiji travels to the programming world, he will seeconnectI was afraid that my beard would be shaken off because of my smile, and I had to mutter in my heart: "The connect of this signal slot has so many changes, which is amazing!"

Imagine, weconnectFunctions are simply "versatile experts" in programming. They can not only relate to old function pointers, but also secretly send misunderstandings to the trendy Lambda expressions, and also have some ambiguous relationships with the signal mapping mechanism. Isn't this? Just like Kong Yiji studied several ways of writing the word "wind", we programmers also have to think about it.connectSeveral poses -_-||b

When choosing which writing method, it should be determined based on the specific needs and code style. For complex slot function logic, traditional slot function may be more suitable; for simple logic or temporary connections, Lambda expressions may be more convenient; and for function pointersconnectIt is usually a compromise choice, safe and easy to use.

Summarize

This is the end of this article about several ways to write connect in Qt C++. For more related content on the writing of connect in Qt C++, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!