c++ - 使用指向动态分配的派生类的指针填充私有(private)静态类 map<string,Base*>

标签 c++ class templates

我有一个类 Central 的私有(private)静态成员变量,类型映射。我想用“Base* ”指针填充此映射,这些指针指向派生自“Base ”的类的实例。这些派生类的实例必须存储在动态内存中。还涉及一些模板乐趣。我确实尝试了一种填充 map 的方法,但它给了我一个编译错误(稍后会说明)。

为了清楚起见,这里有一个代码片段:

#include <all_necesary_std_headers>

class Base
{
    /* guts */
};

template<class CType>
class Derived: public Base
{
    /* innards */
};

class Central
{
    /* partial entrails */
private:
    // the static map I was referring to
    static std::map<string, Base*> base_map;
};

// Initializing the static map here
std::map<string, Base*> Central::base_map;

class Test1
{
    /* viscera */
};

// Compilation error here, on next line of code.
Central::base_map["Test1"] = dynamic_cast<Base*>( new Derived<Test1>);

class Test2
{
    /* bowels */
};

// Compilation error here, on next line of code.
Central::base_map["Test2"] = dynamic_cast<Base*>( new Derived<Test2>);

这是我得到的编译错误: 错误:在“=”标记之前需要构造函数、析构函数或类型转换;

我已经有一个析构函数来释放映射分配的内存,所以不需要提醒我。我想在 main() 中使用“Central”类。该类结构将用于根据存储在文件中的类名动态创建类的新实例。

希望一切都清楚,如果有什么不明白的请说。

最佳答案

赋值语句只能在函数中进行,不能在命名空间范围内进行。

在 C++11 中,您可以在其声明中初始化映射:

std::map<string, Base*> Central::base_map = {
    {"Test1", new Derived<Test1>},
    {"Test2", new Derived<Test2>}
};

如果您停留在过去,那么您将需要使用一个函数来填充 map ;也许是这样的:

std::map<string, Base*> make_base_map() {
    std::map<string, Base*> map;
    map["Test1"] = new Derived<Test1>;
    map["Test2"] = new Derived<Test2>;
    return map;
}

std::map<string, Base*> Central::base_map = make_base_map();

另请注意,您不能使用 dynamic_cast除非这些类型是多态的(即 Base 至少有一个虚函数)。您可以转换 Derived<T>*Base*没有 Actor ,就像我在我的例子中所做的那样;但是如果你需要用 dynamic_cast 转换回来那么您需要确保它们是多态的。

更新:如果您希望能够通过仅向该类的实现文件添加代码来分别注册每个类,那么您需要声明一个静态对象以在其构造函数中注册该类。现在我们遇到了初始化顺序的问题:如果静态对象在不同的​​翻译单元中初始化,那么初始化顺序是未指定的,因此您不能安全地从另一个的构造函数访问一个。

我们可以通过使 map 成为局部静态变量来解决这个问题,并在第一次访问时初始化:

static std::map<string, Base*> & base_map() {
    static std::map<string, Base*> map;
    return map;
}

现在我们可以定义类来注册类了:

template <typename T>
struct BaseMapEntry {
    explicit BaseMapEntry(string name) {
        base_map()[name] = new Derived<T>;
    }
};

并将它用于每个类:

// header file
class Test1
{
    static BaseMapEntry<Test1> entry;
    /* gubbins */
};

// source file
BaseMapEntry<Test1> Test1::entry("Test1");

(或者,您可以将其设为源文件中的静态 namespace 范围对象,而不是静态成员;选择主要是为了美观。不幸的是,由于一个定义规则。)

关于c++ - 使用指向动态分配的派生类的指针填充私有(private)静态类 map<string,Base*>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14480148/

相关文章:

java - 浏览文件夹以加载类

c++ - 将 Curiously Recurring Template Pattern (CRTP) 与其他类型参数一起使用

c++ - 具有 O(1) 出队和 O(whatever) 入队的优先级队列

c++ - 如何正确编译并执行 TensorFlow C++ API 示例?

c++ - 使用面向对象注册窗口类

c++ - 堆栈地址是否由堆地址共享?

c# - 你如何迭代 .Net 中一个类的 child ?

java - 类的 ArrayList。使困惑

PHP 函数与站点模板的包含

c++ - 调用模板 ctor 时未解析的外部符号