簡體   English   中英

Qt:信號和插槽與C ++:消息傳遞

[英]Qt:Signals and Slots vs C++:Message Passing

我有兩節課

class Car
{
// class Car related methods
public:
setDriversName(QString);
private:
String driversName_;    // This information comes from class DriversName

//Must get the drivers name info, when a particular event in this object occurs;
}

class DriversName
{
//class DriversName related methods
String getDriversName();
private:
String driversName_;
}

所以,現在我想在兩個類之間進行通信,更具體地說, 當Car Object中出現特定事件時 ,我希望類CarDriversName類中獲取驅動程序的名稱。

到目前為止,我有這兩種方式,

C++ Message passing:

class Car
{
// class Car related methods
public:
setDriversNameObject(DriversName& );
setDriversName()
{
   driversName_ =  DriversName.getDriversName();
}

private:
DriversName driversName_;    // So after setting the Driverclass object, i can directly 
//access the driver's name, whenever the event occurs
String driversName_;
}

class DriversName
{
//class DriversName related methods
String getDriversName();

private:
DriversName driversName_;
}

要么

Qt

In mainWindow class:

connect(carObject,eventHasOccured(),this,updateDriversName());


void MainWindow::updateDriversName()
{
    carObject->setDriversName(driversNameObject.getDriversName);
}

Class Car
{
    Q_OBJECT
    signals:
    emit eventHasOccured();

    public:
    setDriversNameObject(DriversName& );

    private:
    DriversName driversName_;              
}

Class DriversName
{
    Q_OBJECT

    String getDriversName();

    private:
    DriversName driversName_;    
}

兩種解決方案肯定都會有效。 這是我的問題:

1)就OO原則而言,上述方法是否存在任何缺陷。

2)這種情況可以處理的最標准方法是什么?

3)還有其他更好的方法來處理給定的情況。

謝謝。

1)就OO原則而言,上述方法是否存在任何缺陷。

第一種方法將Car方法與DriversName類緊密DriversName

第二個將您的申請與Qt聯系起來。 如果你在整個應用程序中使用它,那不是什么大問題,但應該考慮它。 此外,它將業務邏輯代碼移動到主窗口類中,這可能不是一個好主意。

2)這種情況可以處理的最標准方法是什么?

這樣做沒有“一種明確的方式”。 只是越來越好。

3)還有其他更好的方法來處理給定的情況。

對於“純C ++”方法,您可以引入一個抽象接口來監聽驅動程序名稱更改(或者甚至更一般地用於監聽通用名稱更改)。 我在這里指的是基本上實現Observer模式。 簡化的實現可以如下所示:

class NameChangeListener
{
public:
    virtual void onNameChange(std::string const & newName) =0;
};

// This assumes change is initiated in DriversName class - not sure if this is correct
// Your code doesn't show the actual triggering of the change
class DriversName
{
public:
// ... other stuff
    setNameChangeListener(NameChangeListener* ncl)
    {
        changeListener = ncl;
    }
    void setName(std::string const & newName)
    {
        // ... other stuff
        if (changeListener)
            changeListener->onNameChange(newName);
    }
private:
    // ..
    NameChangeListener* changeListener;
};

class Car: public NameChangeListener
{
public:
// ... other stuff
    void onNameChange(std::string const & newName) {
        driversName = newName;
    }
};

// somewhere outside:
Car c1;
DriversName n;
n.setNameChangeListener(c1);

對於Qt方法,可能最好引入一個封裝這種關系的附加“Controller”類,而不是直接在主窗口中進行。

在nyarlathotep的回答之上還有一些細節:

1)如果您確實需要在特定事件發生時進行更新,那么第一個解決方案是不夠的,因為它不處理事件; 一個人應該明確地調用CarsetDriversName() 你需要一般的信號/插槽或回調機制,就像第二種解決方案一樣。 在那種情況下,我認為你寧願需要類似的東西

connect(driversNameObject,nameChanged(string),carObject,setDriversName(string));

應用程序/主窗口和carObject需要知道有關driversNameObject任何信息。 除此之外,我認為你的第二個解決方案中存在一些小錯誤(例如, Car沒有setDriversName方法。

2)和3)如果我還沒有在QT項目中工作,我個人會避免使用QT的信號/插槽機制。 這種機制完全繞過C ++語言,需要通過自己的工具進行源文件預處理。 一個結果是在編譯器有任何檢查機會之前,所有內容(如方法名稱)都被處理為字符串。 另一個是你需要一種特定的方式來構建你的項目,這種方式比必要的更復雜,並且會使其他庫的使用更加困難。

至於更多“純C ++”解決方案,我敢打賭,例如Boost.Signals會完成這項工作,但同樣可能會帶來太多你不需要的復雜性。

我開發了一個純C ++抽象接口,它完全模仿基於委托的QT信號/槽的行為,但這涉及內部的低級內容,如轉換為void* 另一種選擇當然是在內部使用std::function 它在處理所有函數調用語言特性時仍然不是完全通用的,例如派生類中的方法,重載,虛方法,默認參數等等(但Boost.Signals都不是)。 我打算在完成它之前使用可變參數模板在C ++ 11中重新實現它。

同樣,我(仍)不知道完美或事實上的標准解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM