In-depth understanding of signal slot (1)

Source: Internet
Author: User

This article is from A Deeper Look at Signals and Slots, Scott Collins 2005.12.19. It should be noted that the "signal slot" we refer to here not only refers to the signal slot in the Qt library, but also stands at a global height and understands the signal slot from the system perspective. So in this article, the Qt signal slot is only introduced as an implementation. We will also introduce the implementation of another signal slot-boost: signal. Therefore, when you see some signal names in the article, you may just write them out to describe them conveniently. Actually, this signal does not exist.

What is a signal slot?

We can answer this question from two perspectives: one is shorter and the other is longer.

Let's answer this question in the simplest language-what is a signal slot?

  • The signal slot is an implementation of the observer mode, or a sublimation;
  • A signal is an event that can be observed, or at least a notification that has occurred;
  • A slot is an observer, usually when the observed object changes-or when the signal is sent-The called function;
  • You can connect the signal to the slot to form a relationship between the observer and the observer;
  • When an event or status changes, the signal is sent. At the same time, the signal sender is obligated to call all registered function slots interested in the event signal ).

There is a many-to-many relationship between the signal and the slot. One signal can be connected to multiple slots, and one slot can also listen to multiple signals.

The signal can have additional information. For example, a window may send a windowClosing signal when it is closed, and this signal can contain a window handle to indicate which window sends the signal; A slider may send a signal when it slides, which contains the specific position of the slider or a new value. We can understand the signal slot as a function signature. Signals can only be connected to slots with the same signature. You can regard the signal as an image name of the underlying event. For example, the windowClosing signal indicates that the window Close event is triggered.

The signal slot is actually irrelevant to the language. There are many ways to implement the signal slot. Different implementation mechanisms will cause a large difference in the signal slot. The term signal slot was initially from the Qt library of Trolltech and has now been acquired by Nokia ). In 1994, the first version of Qt was released, bringing us the concept of a Signal slot. This concept immediately attracted the attention of the computer scientific community and put forward a variety of different implementations. Nowadays, the signal slot is still one of the core of the Qt library, and many other libraries provide similar implementations, even some tool libraries dedicated to providing this mechanism.

After simply understanding the signal slot, let's answer this question from another perspective: What is the signal slot? Where did they come from?

We have learned about the concept of the signal slot. Next we will discuss from a more detailed perspective how the signal slot mechanism develops step by step and how to use them in your own code.

A very important part of programming is component Interaction: one part of the system needs to tell the other part to complete some operations. Let's start with a simple example:

// C++class Button{public:    void clicked(); // something that happens: Buttons may be clicked};class Page{public:    void reload(); // ...which I might want to do when a Button is clicked};

In other words, the Page class knows how to re-load the Page reload), the Button has an action that is to click ). Suppose we have a function that returns the current page currentPage (). When the button is clicked, the current page should be reloaded.

// C++ --- making the connection directlyvoid Button::clicked(){    currentPage()->reload(); // Buttons know exactly what to do when clicked}

This does not look good. The Button class name seems to imply that this is a reusable class, but the click operation of this class is tightly coupled with the Page. This makes it necessary to call the reload () function of currentPage () as long as the button is clicked. This cannot be reused at all. It may be better to rename it PageReloadButton.

In fact, it must be said that this is indeed an implementation method. If the Button: click () function is virtual, you can write a new class to inherit the Button:

// C++ --- connecting to different actions by specializingclass Button{public:    virtual void clicked() = 0; // Buttons have no idea what to do when clicked};class PageReloadButton : public Button{public:    virtual void clicked() {        currentPage()->reload();    // ...specialize Button to connect it to a specific action    }};

Now the Button can be reused. However, this is not a good solution.

Introduce callback

Let's stop and think about how we can solve this problem in the era of only C. If only C exists, there is no such thing as virtual. There are many ways to reuse, but since there is no class help, we adopt another solution: function pointer.

/* C --- connecting to different actions via function pointers */void reloadPage_action( void* ) /* one possible action when a Button is clicked */{    reloadPage(currentPage());}void loadPage_action( void* url ) /* another possible action when a Button is clicked */{    loadPage(currentPage(), (char*)url);}struct Button {    /* ...now I keep a (changeable) pointer to the function to be called */    void (*actionFunc_)();    void* actionFuncData_;};void buttonClicked( Button* button ){    /* call the attached function, whatever it might be */    if ( button && button->actionFunc_ )        (*button->actionFunc_)(button->actionFuncData_);}

This is commonly referred to as "Callback ". The buttonClicked () function does not know which function to call during compilation. The called function is passed in at runtime. In this way, our buttons can be reused, because we can pass different function pointers at runtime to obtain different click operations.

Add type security

C ++ or Java programmers always do not like this. Because this is not a type-safe note, the url has one-step forced type conversion ).

Why do we need type security? The type of an object actually implies how you will use this object. With a clear object type, you can let the compiler help you check whether your code is correctly used, as if you have drawn a boundary and told the compiler that if someone crosses the border, an error is reported. However, if there is no type security, you will lose this advantage, and the compiler will not be able to help you complete this maintenance. This is just like driving a car. As long as you have enough speed, you can let your car fly, but in general, this speed will remind you that this is too insecure. At the same time, some devices, such as radar, will always help you check this situation. This is just like what the compiler has done for us. It is within the scope of our safe use.

Come back and check out our code. Using C is not of type security, but with C ++, we can put the callback function pointer and data in a class to gain the advantage of type security. For example:

// re-usable actions, C++ style (callback objects)class AbstractAction{public:    virtual void execute() = 0; // sub-classes re-implement this to actually do something};class Button{    // ...now I keep a (changeable) pointer to the action to be executed    AbstractAction* action_;};void Button::clicked(){    // execute the attached action, whatever it may be    if ( action_ )        action_->execute();}class PageReloadAction : public AbstractAction    // one possible action when a Button is clicked{public:    virtual void execute() {        currentPage()->reload();    }};class PageLoadAction : public AbstractAction    // another possible action when a Button is clicked{public:    // ...    virtual void execute() {        currentPage()->load(url_);    }private:    std::string url_;};

Okay! Our buttons can be easily reused and are also type-safe, and there is no forced type conversion. This implementation can solve most of the problems encountered in the system. It seems that the current solution is similar to the previous one and inherits a class. But now we abstract the action, and previously abstract the Button. This is similar to the previous C implementation. We associate different actions with buttons. Now we can find a satisfactory method step by step.

This article is from the "bean space" blog, please be sure to keep this source http://devbean.blog.51cto.com/448512/417658

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.