首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 信號槽庫實戰:sigslot.h 與 sigc++ 完整使用指南

     編輯:關於C++

前言

Qt 的信號槽機制雖強大,但依賴 MOC 預處理。若需在非 Qt 專案中使用輕量級、純 C++ 的信號槽庫,sigslot.h(單頭文件、簡單易用)與 sigc++(功能豐富、支援更多特性)是兩大主流選擇。本文詳解兩者在 Visual Studio 環境下的配置與核心用法。

sigslot.h:極簡信號槽實現

獲取與配置

  • 官方地址:sigslot.sourceforge.net
  • VS2013 修正:在 sigslot.h 第 420 行,將
    typedef sender_set::const_iterator const_iterator;
    改為
    typedef typename sender_set::const_iterator const_iterator;

核心概念

概念說明
signal0 ~ signal8信號類,模板參數對應 0~8 個參數,作為類成員
has_slots<>槽類需公開繼承此基類
槽函數返回值必須為 void,參數與對應信號一致
連接signal.connect(&slotObj, &SlotClass::func)
斷開disconnect() / disconnect_all()
發射signal.emit(args...) 或直接 signal(args...)

完整範例:互動式物件控制

#include 
#include 
#include 
#include 
using namespace std;
using namespace sigslot;

enum ObjState { Normal = 0, Hidden = 1 };

class ObjectBase : public has_slots<> {
    int px, py;
    ObjState state;
public:
    ObjectBase(int x=0, int y=0) : px(x), py(y), state(Normal) {}
    void onMoveBy(const int& x, const int& y) { px += x; py += y; }
    void onResize(const int& x, const int& y) { px = x; py = y; }
    void onSetState(ObjState s) { state = s; }
    void onPrintState() {
        cout << (state == Normal ? "Normal" : "Hidden") << endl;
    }
    int getX() const { return px; }
    int getY() const { return py; }
};

class Control {
public:
    signal2 moveBy;
    signal2 resize;
    signal1 setState;
    signal0<> printState;
};

int main() {
    ObjectBase obj(10, 10);
    Control ctrl;
    ctrl.moveBy.connect(&obj, &ObjectBase::onMoveBy);
    ctrl.resize.connect(&obj, &ObjectBase::onResize);
    ctrl.setState.connect(&obj, &ObjectBase::onSetState);
    ctrl.printState.connect(&obj, &ObjectBase::onPrintState);

    while (true) {
        system("cls");
        cout << "Object Info\n  Pos: (" << obj.getX() << ", " << obj.getY() << ")\n  State: " << obj.getState() << "\n";
        cout << "Commands: m/M(move), r/R(resize), s/S(set state), p/P(print), q/Q(quit)\nInput: ";
        char ch = _getch();
        switch (ch) {
            case 'm': ctrl.moveBy(10, 10); break;
            case 'M': ctrl.moveBy.emit(-20, -20); break;
            case 'r': case 'R': ctrl.resize.emit(0, 0); break;
            case 's': ctrl.setState(Normal); break;
            case 'S': ctrl.setState.emit(Hidden); break;
            case 'p': case 'P': ctrl.printState.emit(); _getch(); break;
            case 'q': case 'Q': return 0;
        }
    }
}

sigc++:功能更強大的信號槽框架

編譯與配置要點

  • 官方地址:libsigc.sourceforge.net
  • VS 高版本編譯常見問題:
    • 缺少 msvc_recommended_pragmas.h:專案屬性 → C/C++ → 高級 → 強制包含文件 中移除,或自行添加空文件。
    • 缺少 slot.cc 等文件:可從低版本複製至對應目錄。
  • 專案設定:包含目錄加入 sigc++ 路徑,鏈接庫文件(Debug: sigcd.lib,Release: sigc.lib)。

核心 API 對比

特性sigslotsigc++
信號聲明signalN<Params>sigc::signal<Ret, Params> 或 signalN
槽類基類has_slots<>sigc::trackable
連接全局函數直接取址sigc::ptr_funN
連接成員函數直接取址sigc::mem_funN / sigc::mem_fun(*this, &Class::func)
連接對象sigc::connectionsigc::connection(可選,析構時自動斷開)
發射emit() 或 ()emit()

sigc++ 完整範例

#include 
#include 
#include 
#include 
using namespace std;

#ifdef _DEBUG
#pragma comment(lib, "sigc280d.lib")
#else
#pragma comment(lib, "sigc280.lib")
#endif

enum ObjState { Normal = 0, Hidden = 1 };

class ObjectBase : public sigc::trackable {
    int px, py;
    ObjState state;
    sigc::signal putMsg;
public:
    ObjectBase(int x=0, int y=0) : px(x), py(y), state(Normal) {
        putMsg.connect(sigc::mem_fun(*this, &ObjectBase::printMsg));
    }
    void onMoveBy(const int& x, const int& y) { px += x; py += y; }
    void onResize(const int& x, const int& y) { px = x; py = y; }
    void onSetState(ObjState s) { state = s; }
    void onPrintState() { cout << (state == Normal ? "Normal" : "Hidden") << endl; }
    int getX() const { return px; }
    int getY() const { return py; }
private:
    void printMsg(const char* str) { cout << str << endl; }
};

class Control {
public:
    sigc::signal moveBy;
    sigc::signal resize;
    sigc::signal setState;
};

int printSpaceStr(const char* str) {
    for (const char* p = str; *p; ++p) cout << *p << ' ';
    cout << endl;
    return 0;
}

int main() {
    ObjectBase obj(0, 0);
    Control ctrl;
    sigc::signal printSS;
    printSS.connect(sigc::ptr_fun(&printSpaceStr));
    sigc::signal printState;
    printState.connect(sigc::mem_fun(obj, &ObjectBase::onPrintState));

    ctrl.moveBy.connect(sigc::mem_fun(obj, &ObjectBase::onMoveBy));
    ctrl.resize.connect(sigc::mem_fun(obj, &ObjectBase::onResize));
    ctrl.setState.connect(sigc::mem_fun(obj, &ObjectBase::onSetState));

    while (true) {
        system("cls");
        obj.putMsg.emit("Object Information");
        cout << "  Pos: (" << obj.getX() << ", " << obj.getY() << ")\n";
        cout << "Commands: m/M(move), r/R(resize), s/S(state), p/P(print), a/A(space), q/Q(quit)\nInput: ";
        char ch = _getch();
        switch (ch) {
            case 'm': ctrl.moveBy.emit(10, 10); break;
            case 'M': ctrl.moveBy.emit(-20, -20); break;
            case 'r': case 'R': ctrl.resize.emit(0, 0); break;
            case 's': ctrl.setState.emit(Normal); break;
            case 'S': ctrl.setState.emit(Hidden); break;
            case 'p': case 'P': printState.emit(); _getch(); break;
            case 'a': case 'A': printSS.emit("Sigc_Demo"); _getch(); break;
            case 'q': case 'Q': return 0;
        }
    }
}

選型建議

  • sigslot:單文件、零依賴、適合嵌入式或輕量專案,API 直觀。
  • sigc++:支援綁定、適配器、類型安全、自動生命週期管理(trackable),適合大型專案。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved