将普通成员变量转换为静态成员变量会导致问题

时间:2011-11-24 17:17:55

标签: c++ static-members

我曾经有一个普通的成员变量,它在构造函数中初始化如下:

ResourceSaveFunctions[OBJECTS_IDENT] = NULL;
ResourceSaveFunctions[SPRITES_IDENT] = &GMProject::SaveSprite;
ResourceSaveFunctions[SOUNDS_IDENT] = &GMProject::SaveSound;
ResourceSaveFunctions[BACKGROUNDS_IDENT] = &GMProject::SaveBackground;
ResourceSaveFunctions[PATHS_IDENT] = NULL;
ResourceSaveFunctions[SCRIPTS_IDENT] = NULL;
ResourceSaveFunctions[FONTS_IDENT] = NULL;
ResourceSaveFunctions[TIMELINES_IDENT] = NULL;
ResourceSaveFunctions[ROOMS_IDENT] = NULL;
ResourceSaveFunctions["extension"] = &GMProject::SaveExtension;
ResourceSaveFunctions[INCLUDES_IDENT] = NULL;
ResourceSaveFunctions[TRIGGERS_IDENT] = NULL;

变量是一个带有键字符串的映射,以及作为数据成员函数指针的映射。这非常好。但是如上所述,我认为这个地图应该是静态的(?) - 地图的原因只是确定程序在读取文件时应该做什么。 - NULL意思是“什么都不做”。

所以我把它改成了以下内容:

std::map<std::string, GMProject::GMProjectMemFn> GMProject::ResourceSaveFunctions_INIT() {
    std::map<std::string, GMProjectMemFn> tmp;
    tmp.insert(std::make_pair(OBJECTS_IDENT,NULL));
    tmp.insert(std::make_pair(SPRITES_IDENT, &GMProject::SaveSprite));
    tmp.insert(std::make_pair(SOUNDS_IDENT, &GMProject::SaveSound));
    tmp.insert(std::make_pair(BACKGROUNDS_IDENT, &GMProject::SaveBackground));
    tmp.insert(std::make_pair(PATHS_IDENT, NULL));
    tmp.insert(std::make_pair(SCRIPTS_IDENT, NULL));
    tmp.insert(std::make_pair(FONTS_IDENT, NULL));
    tmp.insert(std::make_pair(TIMELINES_IDENT, NULL));
    tmp.insert(std::make_pair(ROOMS_IDENT, NULL));
    tmp.insert(std::make_pair("extension", &GMProject::SaveExtension));
    tmp.insert(std::make_pair(INCLUDES_IDENT, NULL));
    tmp.insert(std::make_pair(TRIGGERS_IDENT, NULL));
    return tmp;
}
const std::map<std::string, GMProject::GMProjectMemFn> GMProject::ResourceSaveFunctions(GMProject::ResourceSaveFunctions_INIT());

在标题中声明这些内容的地方:

static const std::map<std::string, GMProjectMemFn> ResourceSaveFunctions;
static std::map<std::string, GMProjectMemFn> ResourceSaveFunctions_INIT();

现在编译突然出现了很多错误。

  

1&gt; c:\ program files \ microsoft visual studio 10.0 \ vc \ include \ utility(163):错误C2440:'initializing':无法从'int'转换为'GMProject :: GMProjectMemFn'

关于NULL的转换。但是,这不应该是可能的吗?为什么这不可能(但在之前的方法中却是如此)? 我应该在这里使用明确的演员吗?

编辑: GMProjectMemFn定义如下:

typedef void (GMProject::*GMProjectMemFn)(const pTree&) const; 

pTree是一个容器。

2 个答案:

答案 0 :(得分:1)

std::make_pair创建pair<T1, T2>,其中T1T2类型是从参数类型隐式推断出来的。 NULL扩展为0(或0L),因此在您的情况下make_pair会返回pair<string, int>(或pair<string, long>)。

然后尝试将pair<string, int>传递给map<string, GMProject::GMProjectMemFn>::insert(),但这需要pair<string, GMProjectMemFn>

std::pair有一个通用的复制构造函数,它会尝试对该对的每个成员进行隐式转换:

template <class U, class V>
    pair (const pair<U,V> &p) : first(p.first), second(p.second) { }

但在您的情况下,这需要将const int&转换为指针,这是不允许的。

在原始案例中,您直接将NULL转换为指针,该指针已明确定义。

明确键入pair应该解决此问题:

tmp.insert(std::pair<std::string, GMProject::GMProjectMemFn>(TIMELINES_IDENT, NULL));

答案 1 :(得分:0)

啊。 NULL可能仅定义为文字0,make_pair将其推导为整数,pair<int,int>不能转换为pair<int,GMProjectMemFn>。它通过operator []进行赋值,因为(我猜)从0到GMProjectMemFn的隐式转换。

所以,试着写make_pair(PATHS_IDENT, (GMProjectMemFn)0)