2011-11-16 10 views
12

Ho questo nel mio C++ file di intestazione:Come si popolano i valori di una QMap statica in C++ Qt?

#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 
}; 

Questo è il mio C++ file sorgente:

#include "LogEvent.h" 

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

//blah blah blah other functions 

voglio aggiungere valori al mio statica QMap COLUMN_NAMES. Dove e come lo farei?

+1

Tempo per Qt per aggiungere supporto per C++ 11! –

risposta

14

È possibile utilizzare la funzione statica che restituisce mappa inizializzata:

// 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(); 

Inoltre, nel caso in cui si desidera utilizzare stringhe di internazionalizzazione in variabili statiche e bisogno di chiamare QTextCodec::setCodecForTr prima, è una buona idea per spostare variabile statica nella sua funzione di 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; 
    } 
} 

in questo modo COLUMN_NAMES sarà inizializzato con la prima chiamata di getColumnNames() ed è possibile impostare il codec di testo in anticipo. Ma questo non è thread-safe.

+0

Grazie !. Domanda veloce su thread safe. Quando dici che questa funzione non è thread-safe, vuoi dire che se la mia applicazione è multi-thread, potrebbero esserci problemi corretti? –

+0

Sì, potrebbero apparire problemi quando più thread eseguono codice non thread-safe simultaneamente. In generale, per risolvere questo problema è possibile utilizzare [oggetti di sincronizzazione] (http://doc.qt.nokia.com/4.7/threads-synchronizing.html) come 'QMutex'. Ma in questo caso particolare devi solo garantire che la variabile statica sia inizializzata quando è attivo solo un thread, poiché non dovrebbe essere modificato. – userr1728854

1

È possibile creare std :: map e utilizzarlo per init QMap, o semplicemente sostituire QMap con std :: map:

COLUMN_NAMES
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); 

Un altro modo è init in costruttore:

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

ma questo non è thread-safe, il primo metodo è stato chiamato prima di main, mentre il secondo durante può essere chiamato durante il runtime.

+0

Il primo metodo dovrebbe essere nell'intestazione o nel file sorgente? –

+0

Ordinario, file sorgente. – fghj

24

Nel frattempo, Qt 5.2 ha aggiunto il supporto per C++ 11 liste di inizializzazione in QMap:

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

Ciò significa che è possibile inizializzare la vostra mappa in questo modo:

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

Ho appena provato questo approccio e non si compila, nello stesso tempo tutte le altre caratteristiche di C++ 11 funziona .... lambda ecc., Sei sicuro che sia effettivamente implementato? Sto usando QT5.3.1 errore: nessuna funzione di matching per la chiamata a 'QMap :: QMap ()' –

+0

In realtà ho provato solo con Qt 5.4.0, ma la [documentazione] (http://doc.qt.io/qt-5/qmap.html#QMap-2) dice che è disponibile da Qt 5.1.Hai abilitato C++ 11 correttamente aggiungendo 'CONFIG + = C++ 11' al file .pro? – Luchs

+2

Per completezza: se la mappa è stata dichiarata altrove, è possibile inizializzarla con qualcosa come: 'this-> m_map = QMap ({{" a ", 1}, {" b ", 2}, {"c", 3}}); ' – waldyrious

3

Un altro approccio utilizzando un elenco di inizializzazione.

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

Questo funziona per Qt precedenti prima che Qt fosse stato impostato per funzionare direttamente con gli elenchi di inizializzatori.

Problemi correlati