【问题标题】:Initialize static array of template class with derived class type用派生类类型初始化模板类的静态数组
【发布时间】:2014-11-17 13:43:02
【问题描述】:

我有一个带有 main 函数的程序,它只打印一个字符串。当我运行这个程序时,它在控制台中没有输出就崩溃了。当我将元素插入 OperatorCore (symbolMap) 的映射时,我发现问题发生了。

这是最少的代码:

//Binary.hpp
class Binary final : public OperatorCore, public StaticPool<Binary> {
public:
    Binary(int ID, std::string name)
        : OperatorCore(name), StaticPool<Binary>(ID) {
    }
    ~Binary() {}
};
//Binary.cpp
template<>
const Binary StaticPool<Binary>::pool[] = {
    Binary(0, "a string value")//without this line of code, it prints works
};

//OperatorCore.hpp
class OperatorCore {
public:
    static std::map<std::string, OperatorCore*> symbolMap;
    const std::string name;
    OperatorCore (std::string name);
    virtual ~OperatorCore () {}
};
//OperatorCore.cpp
std::map<std::string, OperatorCore*> OperatorCore::symbolMap{};
OperatorCore::OperatorCore(std::string name) : name(name) {
    symbolMap.insert({name, this});
}


//StaticPool
template<typename T, typename TKey = int>
class StaticPool {
public:
    const TKey ID;
    static const T pool[];
    StaticPool(TKey ID) : ID(ID) {}
    virtual ~StaticPool() {}
};

如果我删除突出显示的行之一,则不会出现此问题。这种设计会导致内存损坏吗?

编辑OperatorCore::symbolMap的初始化在同一个文件中,也是OperatorCore构造函数的实现。

【问题讨论】:

    标签: c++ templates inheritance initialization multiple-inheritance


    【解决方案1】:

    我怀疑您有初始化顺序问题。换句话说,您的程序尝试在symbolMap 之前初始化pool,并且Binary 对象的构造函数调用基构造函数,它尝试使用尚未构造的symbolMap

    对此有多种解决方案。您最好的选择可能是将 symbolMap 静态成员转换为特殊 getter 函数内的静态变量:

    class OperatorCore {
    public:
        static std::map<std::string, OperatorCore*>& symbolMap() {
            static std::map<std::string, OperatorCore*> instance;
            return instance;
        }
    };
    

    【讨论】:

    • symbolMap的初始化和OperatorCore的构造函数的实现在同一个.cpp文件中。
    • OperatorCore 的构造函数的代码无关紧要。重要的是OperatorCore::symbolMapStaticPool&lt;Binary&gt;::pool 的定义在不同的文件中。
    【解决方案2】:

    您有一个static initialization order fiasco 的案例。这意味着您的静力学可能以错误的顺序构建。我不知道以正确的顺序初始化 同一个文件 中的静态对象是否有效。但否则你应该延迟依赖于地图的池的初始化。也许编写一个函数来初始化池并在 main 的开头调用它。

    【讨论】:

    • 是的,我编辑了这个问题。初始化在同一个文件 cpp 文件中,其中也是 che OperatorCore 构造函数主体。 std::map&lt;std::string, OperatorCore*&gt; OperatorCore::symbolMap{};
    • @biowep:请更正构造函数名称,并显示初始化,以便我们看到顺序。另一个想法是从函数初始化池,但前提是之前的部分失败。也许提供一个完整的 MWE(带有一个主要功能)
    • @biowep:顺便说一下,您使用的是 cpp11,您应该能够内联初始化静态成员。
    • 如果这样做,我会收到错误:in-class initialization of static data member 'std::map&lt;std::basic_string&lt;char&gt;, OperatorCore*&gt; OperatorCore::symbolMap' of incomplete type
    • @biowep: class x { static templateType&lt;x*&gt; y={} } 除了给你上述错误之外别无选择,除非你给出一个前向声明。但你的问题在别处,你有一个static initialization order fiasco
    猜你喜欢
    • 2010-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-10
    • 1970-01-01
    相关资源
    最近更新 更多