我有一个类 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/