如何在 C++ Qt 中填充静态 QMap 的值?

Posted

技术标签:

【中文标题】如何在 C++ Qt 中填充静态 QMap 的值?【英文标题】:How do I populate values of a static QMap in C++ Qt? 【发布时间】:2011-11-16 19:40:55 【问题描述】:

我的 C++ 头文件中有这个:

#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 COLUMN_NAMES。我将在哪里以及如何做到这一点?

【问题讨论】:

Qt 是时候添加一些 C++11 支持了! 【参考方案1】:

同时,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;

【讨论】:

我刚刚尝试过这种方法,但它无法编译,同时所有其他 C++11 功能都可以工作...... lambdas 等,你确定它真的实现了吗?我正在使用 QT5.3.1 错误:没有匹配函数调用 'QMap::QMap()' 我实际上只在 Qt 5.4.0 上尝试过这个,但documentation 表示它从 Qt 5.1 开始可用。您是否通过在 .pro 文件中添加 CONFIG += c++11 正确启用了 C++11? 为了完整起见:如果地图已在其他地方声明,您可以使用以下内容对其进行初始化:this-&gt;m_map = QMap&lt;QString, int&gt;( "a", 1, "b", 2, "c", 3 ); 这不是最佳方式,因为插入单对 (对于 std::map 和 QMap)会生成 1 个 CustomStruct 构造函数、两个构造函数副本和两个析构函数。如果你使用userr1728854提到的静态函数的方法,它只会生成一个构造函数,一个构造函数副本和一个析构函数。【参考方案2】:

您可以使用返回初始化地图的静态函数:

// 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() 时被初始化,您可以预先设置文本编解码器。但这不是线程安全的。

【讨论】:

谢谢!。关于线程安全的快速问题。当你说这个函数不是线程安全的时,你的意思是如果我的应用程序是多线程的,可能会有问题正确吗? 是的,当多个线程同时执行非线程安全代码时可能会出现问题。通常,要解决此问题,您可以使用synchronization objects,如QMutex。但在这种特殊情况下,您只需要保证只有一个线程处于活动状态时初始化静态变量,因为它不应该被修改。【参考方案3】:

另一种使用初始化列表的方法。

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

这适用于在 Qt 被修复为直接使用初始值设定项列表之前的旧 Qt。

【讨论】:

【参考方案4】:

您可以创建 std::map 并使用它来初始化 QMap,或者只是将 QMap 替换为 std::map:

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

另一种方法是在构造函数中初始化 COLUMN_NAMES:

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

但这不是线程安全的,第一个方法在 main 之前调用,而第二个 during 可能在运行时调用。

【讨论】:

第一种方法应该在头文件还是源文件中?

以上是关于如何在 C++ Qt 中填充静态 QMap 的值?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Qt 的 QTableView 中显示一个简单的 QMap?

qt编程,两个QString的值呼唤。

QMap 与 QHash

QT如何设置可变的全局变量

Qt532.容器QMap&QMultiMap

Qt每天一例15.QMap添加操作