2011-11-16 37 views
12

我有這個在我的C++頭文件:如何在C++ Qt中填充靜態QMap的值?

#include <QMap> 
#include <QString> 

class LogEvent { 

public: 
    LogEvent(); 

    enum column_t {TIMESTAMP_COLUMN = 0, TYPE_COLUMN = 1, EVENT_COLUMN = 2, 
     FILE_COLUMN = 3}; 
    static QMap<column_t, QString> COLUMN_NAMES; 

    static QMap<column_t, QString> getColumnNames() { 
     return LogEvent::COLUMN_NAMES; 
    } 

    //blah blah blah other functions 
}; 

這是我的C++源文件:

#include "LogEvent.h" 

LogEvent::LogEvent() 
{ 
    //constructor code 
} 

//blah blah blah other functions 

我要值添加到我的靜態QMAP的欄。我在哪裏以及如何做到這一點?

+1

Qt添加一些C++ 11支持的時間! –

回答

14

您可以使用靜態函數返回初始化的地圖:

// source file: 
QMap<column_t, QString> LogEvent::initColumnNames() { 
    QMap<column_t, QString> map; 
    map.insert(LogEvent::TIMESTAMP_COLUMN,"Timestamp"); 
    // and so on 
    return map; 
} 

QMap<column_t, QString> LogEvent::COLUMN_NAMES = initColumnNames(); 

此外,如果你想使用字符串國際化的靜態變量,需要調用QTextCodec::setCodecForTr第一,它是將靜態變量是個好主意到其getter函數:

class LogEvent { 

public: 
// ... 
    static QMap<column_t, QString> initColumnNames(); 

    static QMap<column_t, QString> getColumnNames() { 
     static QMap<column_t, QString> COLUMN_NAMES = initColumnNames(); 
     return COLUMN_NAMES; 
    } 
} 

這樣COLUMN_NAMES將與getColumnNames()第一個電話被初始化,您可以預先設定的文本編解碼器。但這不是線程安全的。

+0

謝謝!關於線程安全的快速問題。當你說這個函數沒有線程安全的時候,你的意思是說,如果我的應用程序是多線程的,那麼可能有問題是正確的? –

+0

是的,當多個線程同時執行非線程安全代碼時可能會出現問題。通常,爲了解決這個問題,你可以使用[同步對象](http://doc.qt.nokia.com/4.7/threads-synchronizing.html),比如'QMutex'。但在這種特殊情況下,只需要保證靜態變量在只有一個線程處於活動狀態時被初始化,因爲它不應該被修改。 – userr1728854

1

您可以創建的std ::地圖,並用它來初始化QMAP,​​或者只是用的std ::地圖取代QMAP:

在構造
static const std::pair<T1, T2> arr[] = { 
    std::pair<T1, T2>(v1, v2), 
    std::pair<T1, T2>(v3, v4), 
}; 

static std::map<T1, T2> my_map(arr, arr + sizeof(arr)/sizeof(arr[0])); 
QMap<column_t, QString> LogEvent::COLUMN_NAMES(my_map); 

另一種方式是init:COLUMN_NAMES

LogEvent::LogEvent() { 
    if (COLUMN_NAMES.isEmpty()) 
    ;//init it here 

但這不是線程安全的,第一個方法在main之前調用,而第二個方法可能在運行時調用。

+0

第一種方法應該在頭文件還是源文件中? –

+0

普通,源文件。 – fghj

24

同時,Qt的5.2 QMAP增加了對C++ 11名初始化列表支持:

QMap::​QMap(std::initializer_list<std::pair<Key, T> > list) 

這意味着你可以初始化你的地圖是這樣的:

static QMap<QString, int> my_map{{"a", 1}, {"b", 2}, {"c", 3}}; 
+0

我只是試過這種方法,它不編譯,在同一時間所有öhrhrC++ 11功能工作.... lambdas等,你確定它實際上執行?我正在使用QT5.3.1 錯誤:沒有匹配函數調用'QMap :: QMap(<括號內含的初始化列表>)' –

+0

我實際上只用Qt 5.4.0試過,但[documentation](http://doc.qt.io/qt-5/qmap.html#QMap-2)表示它自Qt 5.1開始就可用。您是否通過向.pro文件添加CONFIG + = C++ 11'來正確啓用C++ 11? – Luchs

+2

爲了完整:如果地圖已經在其他地方聲明過了,你可以用如下方式對它進行初始化:'this-> m_map = QMap ({{「a」,1},{「b」,2}, {「c」,3}});' – waldyrious

3

另一種方法使用初始化器列表。

QMap<QString, QString> qmap_(std::map<QString, QString> {{ "", "" }}); 

這適用於Qt之前的Qt被固定到直接使用初始化列表的工作。