IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    ĺŚ‚ä˝•ĺˆŠç”¨ C++ çš„ Lambda čĄ¨čžžĺźćĺ‡ Qt 䝣码

    scsecrystal发表于 2017-02-09 03:05:15
    love 0

    Lambda čĄ¨čžžĺźć˜Żĺœ¨ C++11 中加兼的 C++ ç‰šć€§ă€‚ĺœ¨čż™çŻ‡ć–‡çŤ ä¸­ćˆ‘äťŹĺ°†çœ‹ĺˆ°ĺŚ‚ä˝•ç”¨ Lambda čĄ¨čžžĺźćĽçŽ€ĺŒ– Qt 䝣码。Lambda ĺžˆĺźşĺ¤§ďźŒä˝†äšŸčŚĺ°ĺżƒĺŽƒĺ¸ŚćĽçš„é™ˇé˜ąă€‚

    éŚ–ĺ…ˆďźŒäť€äšˆć˜Ż Labmda čĄ¨čžžĺźďźŸ

    Lambda čĄ¨čžžĺźć˜Żĺœ¨ćŸä¸Şĺ‡˝ć•°ä¸­ç›´ćŽĽĺŽšäš‰çš„ĺŒżĺĺ‡˝ć•°ă€‚ĺŽƒĺŻäťĽç”¨äşŽäťťä˝•éœ€čŚäź é€’ĺ‡˝ć•°ćŒ‡é’ˆçš„ĺœ°ć–šă€‚

    Lambda čĄ¨čžžĺźçš„čŻ­ćł•ĺŚ‚ä¸‹ďźš

    [čŽˇĺ–ĺ˜é‡](ĺ‚ć•°) {
        lambda 䝣码
    }

    çŽ°ĺœ¨ĺ…ˆĺż˝ç•Ľ â€œčŽˇĺ–ĺ˜é‡â€ čż™éƒ¨ĺˆ†ă€‚ä¸‹é˘ć˜Żä¸€ä¸ŞçŽ€ĺ•çš„ LambdaďźŒç”¨äşŽé€’ĺ˘žä¸€ä¸Şć•°ďźš

    [](int value) {
        return value + 1;
    }

    ćˆ‘äťŹĺŻäťĽćŠŠčż™ä¸Ş Lambda ç”¨äşŽĺƒÂ std::transform()Â čż™ć ˇçš„ĺ‡˝ć•°ďźŒćĽä¸ş vector çš„ćŻä¸€ä¸Şĺ…ƒç´ ĺ˘žĺ€źďźš

    #include 
    #include 
    #include 
    int main() {
        std::vector vect = { 1, 2, 3 };
        std::transform(vect.begin(), vect.end(), vect.begin(),
                       [](int value) { return value + 1; });    for(int value : vect) {
    std::cout

    ć‰“ĺ°çť“ćžœďźš

    2
    3
    4

    čŽˇĺ–ĺ˜é‡

    Lambda čĄ¨čžžĺźĺŻäťĽé€ščż‡ â€œčŽˇĺ–â€ ćĽä˝żç”¨ĺ˝“ĺ‰ä˝œç”¨ĺŸŸä¸­çš„ĺ˜é‡ă€‚ä¸‹é˘ć˜Żç”¨ Lambda 来对 vector ćą‚ĺ’Œçš„ä¸€ä¸Şç¤şäž‹ă€‚

    std::vector vect = { 1, 2, 3 };
    int sum = 0;
    std::for_each(vect.begin(), vect.end(), [&sum](int value) {
        sum += value;
    });

    ä˝ ĺŻäťĽçœ‹ĺˆ°ďźŒćˆ‘äťŹčŽˇĺ–äş†ćœŹĺœ°ĺ˜é‡ sumďźŒć‰€äťĽĺŻäťĽĺœ¨ Lambda ĺ†…éƒ¨ä˝żç”¨ĺŽƒă€‚sum ĺŠ äş†ĺ‰çź€ &ďźŒčż™čĄ¨ç¤şćˆ‘äťŹé€ščż‡ĺź•ç”¨čŽˇĺ– sum ĺ˜é‡ďźšĺœ¨ Lambda ĺ†…éƒ¨ďźŒsum ć˜Żä¸€ä¸Şĺź•ç”¨ďźŒć‰€äťĽĺŻšĺŽƒčż›čĄŒçš„äťťä˝•ć”šĺ˜éƒ˝äźšĺŻš Lambda ĺ¤–éƒ¨çš„ sum ĺ˜é‡é€ ćˆĺ˝ąĺ“ă€‚

    ĺŚ‚ćžœä˝ ä¸ć˜Żéœ€čŚĺź•ç”¨ďźŒĺŞéœ€čŚĺ˜é‡çš„ć‹ˇč´ďźŒĺŞéœ€čŚĺŽťćŽ‰ & 尹弽。

    ĺŚ‚ćžœä˝ ćƒłčŽˇĺ–ĺ¤šä¸Şĺ˜é‡ďźŒĺŞéœ€čŚç”¨é€—ĺˇčż›čĄŒĺˆ†éš”ďźŒĺ°ąĺƒĺ‡˝ć•°çš„ĺ‚ć•°é‚Łć ˇă€‚

    ç›Žĺ‰čż˜ä¸čƒ˝ç›´ćŽĽčŽˇĺ–ćˆĺ‘˜ĺ˜é‡ďźŒä˝†ć˜Żä˝ ĺŻäťĽčŽˇĺ– thisďźŒç„śĺŽé€ščż‡ĺŽƒčŽżé—Žĺ˝“ĺ‰ĺŻščąĄçš„ć‰€ćœ‰ćˆĺ‘˜ă€‚

    ĺœ¨čƒŒĺŽďźŒLambda čŽˇĺ–çš„ĺ˜é‡äźšäżĺ­˜ĺœ¨ä¸€ä¸Şéšč—çš„ĺŻščąĄä¸­ă€‚ä¸čż‡ďźŒĺŚ‚ćžœçź–čŻ‘ĺ™¨çĄŽčŽ¤ Lambda ä¸äźšĺœ¨ĺ˝“ĺ‰ĺą€éƒ¨ä˝œç”¨ĺŸŸäš‹ĺ¤–ä˝żç”¨ďźŒĺŽƒĺ°ąäźščż›čĄŒäź˜ĺŒ–ďźŒç›´ćŽĽä˝żç”¨ĺą€ĺŸŸĺ˜é‡ă€‚

    ćœ‰ä¸€ä¸Şĺˇć‡’çš„ĺŠžćł•ĺŻäťĽčŽˇĺ–ć‰€ćœ‰ĺą€éƒ¨ĺ˜é‡ă€‚ç”¨ [&] ćĽčŽˇĺ–ĺŽƒäťŹçš„ĺź•ç”¨ďź›ç”¨ [=] ćĽčŽˇĺ–ĺŽƒäťŹçš„ć‹ˇč´ă€‚ä¸čż‡ćœ€ĺĽ˝ä¸čŚčż™ć ˇĺšďźŒĺ› ä¸şĺź•ç”¨ĺ˜ć›´çš„ç”Ÿĺ‘˝ĺ‘¨ćœŸĺžˆĺŻčƒ˝çŸ­äşŽ Lambda çš„ç”Ÿĺ‘˝ĺ‘¨ćœŸďźŒčż™äźšĺŻźč‡´ĺĽ‡ć€Şçš„é”™čŻŻă€‚ĺ°ąçŽ—ä˝ čŽˇĺ–çš„ć˜Żä¸€ä¸Şĺ˜é‡çš„ć‹ˇč´ďźŒä˝†ĺŽƒćœŹčşŤć˜Żä¸€ä¸ŞćŒ‡é’ˆďźŒäšŸäźšĺŻźč‡´ĺ´Šćşƒă€‚ĺŚ‚ćžœć˜ŽçĄŽçš„ĺˆ—ĺ‡şä˝ äžčľ–çš„ĺ˜é‡ďźŒäźšć›´ĺŽšć˜“éżĺź€čż™çąťé™ˇé˜ąă€‚ĺ…łäşŽčż™ä¸Şé™ˇé˜ąć›´ĺ¤šçš„äżĄćŻďźŒčŻˇçœ‹çœ‹Â â€œEffective Modern C++” 的珏 31 ćĄă€‚

    Qt 连掼中的 Lambda

    ĺŚ‚ćžœä˝ ĺœ¨ç”¨ć–°çš„čżžćŽĽéŁŽć źÂ (ä˝ ĺş”čŻĽç”¨ďźŒĺ› ä¸şćœ‰éžĺ¸¸ĺĽ˝çš„çąťĺž‹ĺŽ‰ĺ…¨ďź)ďźŒĺ°ąĺŻäťĽĺœ¨ćŽĽć”śçŤŻä˝żç”¨ LambdaďźŒčż™ĺŻšäşŽčžƒĺ°çš„ĺ¤„ç†ĺ‡˝ć•°ćĽčŻ´çŽ€ç›´ĺ¤ŞćŁ’äş†ă€‚

    ä¸‹é˘ć˜Żä¸€ä¸Şç”ľčŻć‹Źĺˇĺ™¨çš„ç¤şäž‹ďźŒç”¨ćˆˇĺŻäťĽčž“ĺ…Ľć•°ĺ­—ç„śĺŽć‹¨ĺ‡şç”ľčŻďźš

    Dialer::Dialer() {
        mPhoneNumberLineEdit = new QLineEdit();
        QPushButton* button = new QPushButton("Call");
        /* ... */
        connect(button, &QPushButton::clicked,
                this, &Dialer::startCall);
    }
    void Dialer::startCall() {
        mPhoneService->call(mPhoneNumberLineEdit->text());
    }

    ćˆ‘äťŹĺŻäťĽä˝żç”¨ Lambda 䝣替 startCall() 斚法

    Dialer::Dialer() {
        mPhoneNumberLineEdit = new QLineEdit();
        QPushButton* button = new QPushButton("Call");
        /* ... */
        connect(button, &QPushButton::clicked, [this]() {
            mPhoneService->call(mPhoneNumberLineEdit->text());
        });
    }

    用 Lambda 䝣替 QObject::sender()

    Lambda äšŸć˜ŻÂ QObject::sender()Â çš„ä¸€ä¸Şéžĺ¸¸ĺĽ˝çš„ć›żäťŁć–šćĄˆă€‚ćƒłĺƒä¸€ä¸‹ďźŒĺŚ‚ćžœćˆ‘äťŹçš„ć‹¨ĺˇĺ™¨çŽ°ĺœ¨ć˜Żä¸€çť„çš„ć•°ĺ­—ćŒ‰é’Žçš„ć•°çť„ă€‚

    沥使用 Labmda çš„äťŁç ďźŒĺœ¨çť„ĺˆć•°ĺ­—çš„ć—śĺ€™äźšĺƒčż™ć ˇďźš

    Dialer::Dialer() {
        for (int digit = 0; digit setProperty("digit", digit);
            
            connect(button, &QPushButton::clicked,
                    this, &Dialer::onClicked);
        }
        /* ... */
    }
    void Dialer::onClicked() {
        QPushButton* button = static_cast(sender());
        int digit = button->property("digit").toInt();
        mPhoneService->dial(digit);
    }

    ćˆ‘äťŹĺŻäťĽä˝żç”¨Â QSignalMapper 嚜厝掉 Dialer::onClicked() ć–šćł•ďźŒä˝†ä˝żç”¨ Labmda äźšć›´çľć´ťć›´çŽ€ĺ•ă€‚ćˆ‘äťŹĺŞéœ€čŚčŽˇĺ–ä¸ŽćŒ‰é’ŽĺŻšĺş”çš„ć•°ĺ­—ďźŒç„śĺŽĺœ¨ Lambda ä¸­ç›´ćŽĽĺ°ąčƒ˝č°ƒç”¨Â mPhoneService->dial()。

    Dialer::Dialer() {
        for (int digit = 0; digit dial(digit);
                }
            );
        }
        /* ... */
    }

    ä¸čŚĺż˜äş†ĺŻščąĄçš„ç”Ÿĺ‘˝ĺ‘¨ćœŸďź

    çœ‹čż™ćŽľäťŁç ďźš

    void Worker::setMonitor(Monitor* monitor) {
        connect(this, &Worker::progress,
                monitor, &Monitor::setProgress);
    }

    ĺœ¨čż™ä¸Şĺ°äž‹ĺ­ä¸­ďźŒćœ‰ä¸€ä¸Ş Worker ĺŽžäž‹ćĽĺ‘ Monitor ĺŽžäž‹ćŠĽĺ‘Ščż›ĺşŚă€‚ĺˆ°ç›Žĺ‰ä¸şć­˘ďźŒčż˜ć˛Ąäť€äšˆé—Žé˘˜ă€‚

    çŽ°ĺœ¨ĺ‡čŽžÂ Worker::progress() ćœ‰ä¸€ä¸Ş int ĺž‹çš„ĺ‚ć•°ďźŒĺšśä¸” monitor çš„ĺŚä¸€ä¸Şć–šćł•éœ€čŚä˝żç”¨čż™ä¸Şĺ‚ć•°ĺ€źă€‚ćˆ‘äťŹäźšĺ°čŻ•čż™ć ˇĺšďźš

    void Worker::setMonitor(Monitor* monitor) {
        // Don't do this!
        connect(this, &Worker::progress, [monitor](int value) {
            if (value setProgress(value);
    	} else {
    	    monitor->markFinished();
    	}
        });
    }

    çœ‹čľˇćĽć˛Ąé—Žé˘˜â€Śâ€Śä˝†ć˜Żčż™ćŽľäťŁç äźšĺŻźč‡´ĺ´Šćşƒďź

    Qt çš„čżžćŽĽçłťçťŸĺžˆć™şčƒ˝ďźŒĺŚ‚ćžœĺ‘é€ć–šĺ’ŒćŽĽć”ść–šä¸­çš„äťťä˝•ä¸€ä¸Şč˘Ťĺˆ é™¤ćŽ‰ďźŒĺŽƒĺ°ąäźšĺˆ é™¤čżžćŽĽă€‚ĺœ¨ćœ€ĺˆçš„ setMonitor() ä¸­ďźŒĺŚ‚ćžœ monitor č˘Ťĺˆ é™¤äş†ďźŒčżžćŽĽäšŸäźšč˘Ťĺˆ é™¤ă€‚ä˝†çŽ°ĺœ¨ćˆ‘äťŹä˝żç”¨äş† Lambda ćĽä˝œä¸şćŽĽć”ść–šďźš Qt ç›Žĺ‰ć˛Ąćœ‰ĺŠžćł•ĺ‘çŽ°ĺœ¨Â Lambda 中使用了 monitoră€‚ĺłä˝ż monitor č˘Ťĺˆ é™¤ćŽ‰ďźŒLambda äťç„śäźšč°ƒç”¨ďźŒçť“ćžœĺş”ç”¨ĺ°ąäźšĺœ¨ĺ°čŻ•ĺź•ç”¨ monitor çš„ć—śĺ€™ĺ‘ç”Ÿĺ´Šćşƒă€‚

    ä¸şäş†éżĺ…ĺ´Šćşƒĺ‘ç”ŸďźŒä˝ čŚĺ‘ connect() č°ƒç”¨äź ĺ…Ľä¸€ä¸Şâ€œcontextâ€ĺ‚ć•°ďźŒĺƒčż™ć ˇďźš

    void Worker::setMonitor(Monitor* monitor) {
        // Do this instead!
        connect(this, &Worker::progress, monitor,
                [monitor](int value) {
    	if (value setProgress(value);
    	} else {
    	    monitor->markFinished();
    	}
        });
    }

    čż™ćŽľäťŁç ä¸­ďźŒćˆ‘äťŹćŠŠ monitor ä˝œä¸şä¸Šä¸‹ć–‡äź ĺ…Ľäş† connect()ă€‚čż™ä¸äźšĺŻš Lambda çš„ć‰§čĄŒé€ ćˆĺ˝ąĺ“ďźŒä˝†ć˜Żĺœ¨ monitor č˘Ťĺˆ é™¤äš‹ĺŽďźŒQt äźšćł¨ć„ĺˆ°ĺšśč§Łé™¤Â Worker::progress() ĺ’Œ Lambda 䚋间的连掼。

    čż™ä¸Şä¸Šä¸‹ć–‡čż˜äźšç”¨äşŽćŁ€ćľ‹čżžćŽĽć˜ŻĺŚĺœ¨é˜Ÿĺˆ—ä¸­ă€‚ĺ°ąĺƒçťĺ…¸çš„ signal-slot čżžćŽĽé‚Łć ˇďźŒĺŚ‚ćžœä¸Šä¸‹ć–‡ĺŻščąĄä¸Žĺ‘ĺ°„äżĄĺˇçš„äťŁç ä¸ĺœ¨ĺŒä¸€ä¸Şçşżç¨‹ďźŒQt äźšĺ°†čżžćŽĽç˝Žĺ…Ľé˜Ÿĺˆ—ă€‚

    䝣替 QMetaObject::invokeMethod

    ä˝ ĺŻčƒ˝ĺŻšä¸€ç§ĺź‚ć­Ľč°ƒç”¨ slot çš„ć–šćł•ćŻ”čžƒç†Ÿć‚‰ďźŒĺŽƒä˝żç”¨Â QMetaObject::invokeMethodă€‚ĺ…ˆĺŽšäš‰ä¸€ä¸Şçąťďźš

    class Foo : public QObject {
    public slots:
        void doSomething(int x);
    };

    ä˝ ĺŻäťĽĺœ¨ Qt 中使用 QMetaObject::invokeMethod ĺœ¨äş‹äťśĺžŞçŽŻčż”ĺ›žć—śč°ƒç”¨Â Foo::doSomething()ďźš

    QMetaObject::invokeMethod(this, "doSomething",
                              Qt::QueuedConnection, Q_ARG(int, 1));

    čż™ćŽľäťŁç äźšĺˇĽä˝œďźŒä˝†ć˜Żďźš

    • 语法太丑
    • éžçąťĺž‹ĺŽ‰ĺ…¨
    • ä˝ ĺż…éĄťĺŽšäš‰ä˝œä¸şÂ slot 的斚法

    ĺŻäťĽé€ščż‡ĺœ¨Â QTimer::singleShot()Â ä¸­č°ƒç”¨ Lambda ćĽäťŁć›żä¸Šé˘çš„äťŁç ďźš

    QTimer::singleShot(0, [this]() {
        doSomething(1);
    });

    čż™ä¸Şć•ˆçŽ‡äźšç¨ä˝Žä¸€äş›ďźŒĺ› ä¸şÂ Â QTimer::singleShot() äźšĺœ¨čƒŒĺŽĺˆ›ĺťşä¸€ä¸ŞĺŻščąĄďźŒä¸čż‡ďźŒĺŞčŚä˝ ä¸ć˜ŻčŚĺœ¨ä¸€ç§’ĺ†…č°ƒç”¨ĺžˆĺ¤šćŹĄďźŒčż™ç‚šć€§čƒ˝ćŸĺ¤ąĺŻäťĽĺż˝ç•Ľä¸čŽĄă€‚ć˜žç„śĺˆŠĺ¤§äşŽĺźŠă€‚

    ä˝ ĺŒć ˇĺŻäťĽĺœ¨ Lambda ĺ‰é˘ćŒ‡ĺŽšä¸€ä¸Şä¸Šä¸‹ć–‡ďźŒčż™ĺœ¨ĺ¤šçşżç¨‹ä¸­éžĺ¸¸ćœ‰ç”¨ă€‚ä˝†čŚĺ°ĺżƒďźšĺŚ‚ćžœä˝ ä˝żç”¨ä˝ŽäşŽ 5.6.0 ç‰ˆćœŹçš„ QtďźŒQTimer::singleShot() ćœ‰ä¸€ä¸Ş BUGÂ ĺœ¨ĺ¤šçşżç¨‹ä¸­ä˝żç”¨ć—śäźšĺŻźč‡´ĺ´Šćşƒă€‚ćˆ‘äťŹć‰žĺˆ°äş†é‚Łä¸Şĺ›°éšžçš„ĺŠžćł•â€Śâ€Ś

    关锎炚

    • 连掼 Qt 寚蹥的旜候使用 Lambda ćŻ”ä˝żç”¨č°ƒĺşŚć–šćł•ć›´ĺĽ˝
    • ĺœ¨ connect() č°ƒç”¨ä¸­ä˝żç”¨ Lambda ä¸€ĺŽščŚćœ‰ä¸Šä¸‹ć–‡
    • ćŒ‰éœ€čŽˇĺ–ĺ˜é‡

    ĺ¸Œćœ›ä˝ čƒ˝ĺ–œćŹ˘čż™çŻ‡ć–‡çŤ ďźŒĺšśĺ¸Œćœ›ä˝ çŽ°ĺœ¨ĺ°ąç”¨ćź‚äşŽçš„ Lambda čŻ­ćł•ć›żć˘ćŽ‰ĺ¤ćżçš„ć—§čŻ­ćł•ďź

    ĺŚ‚ä˝•ĺˆŠç”¨ C++ çš„ Lambda čĄ¨čžžĺźćĺ‡ Qt äťŁç ďźŒéŚ–ĺ‘äşŽć–‡çŤ  - äźŻäšĺœ¨çşżă€‚



沪ICP备19023445号-2号
友情链接