多态成员变量指针的std :: map [英] std::map of polymorphic member variables pointers

查看:74
本文介绍了多态成员变量指针的std :: map的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实现与字符串键关联的成员变量指针的映射.所有变量范围从基类BaseA"从映射访问变量时,仅需要使用基类方法(示例中的getDesc()),因此不必检索原始类型.

I'm working on implementing a map of member variables pointers associated with a string key. All variables range from a base class "BaseA" When accessing the variables from the map, it is only required to use the base class methods (getDesc () in the sample) so it is not necessary to retrieve the original type.

此代码可在GNU g ++ 6.2.1下编译并运行,但是根据我的读物,reinterpret_cast的使用不可移植,并且可能无法与其他编译器一起使用.这样对吗?还是此代码符合C ++标准?没有使用reinterpret_cast的方法还有其他方法吗?一项要求是,"Vars"必须可以使用默认的复制构造函数和复制分配实现来复制.

This code compiles and runs under GNU g ++ 6.2.1, but according to what I read, the use of reinterpret_cast is not portable and may not work with other compilers. Is this correct? Or does this code comply with C ++ standards? Is there any other way to do this without using the reinterpret_cast? One requirement is that "Vars" must be copyable with the default copy-contructor and copy-assignment implementations.

示例代码:

#include <iostream>
#include <sstream>
#include <map>
#include <typeinfo>

using namespace std;

struct BaseA
{
    virtual string getDesc()  = 0;
};

struct A1 : BaseA
{
    string getDesc() override { return "This is A1"; }
};

struct A2 : BaseA
{
    string getDesc() override { return "This is A2"; }
};

struct Vars
{
    A1 a1;
    A2 a2;

    map< string, BaseA Vars::* > vars;

    Vars()
    {
        vars["A1_KEY"] = reinterpret_cast<BaseA Vars::*>(&Vars::a1);
        vars["A2_KEY"] = reinterpret_cast<BaseA Vars::*>(&Vars::a2);
    }

    BaseA& get( const string& key )
    {
        auto it = vars.find( key );
        if ( it != vars.end())
        {
            return this->*(it->second);
        }
        throw std::out_of_range( "Invalid variable key:[" + key + "]");
    }
};                                

int main()
{
    Vars v;

    cout << "a1 description :" << v.get("A1_KEY").getDesc() << endl;
    cout << "a2 description :" << v.get("A2_KEY").getDesc() << endl;

    return 0;
}

推荐答案

是的,有 reinterpret_cast 将会做什么的很少保证,从一个指针到成员的指针转换为另一个指针并不是其中之一(除非您随后将其转换回原始类型,否则不会转换)确实有帮助).

Yes, there are very few guarantees about what reinterpret_cast will do, and casting from one pointer to member to another is not one of them (unless you then cast back to the original type, which doesn't really help you).

使用此方法的安全简便方法是使用 std :: function :

The safe and easy way to do this one is using std::function:

struct Vars
{
    A1 a1;
    A2 a2;

    map< string, std::function<BaseA&(Vars&)> > vars;

    Vars()
    {
        vars["A1_KEY"] = &Vars::a1;
        vars["A2_KEY"] = &Vars::a2;
    }

    BaseA& get( const string& key )
    {
        auto it = vars.find( key );
        if ( it != vars.end())
        {
            return it->second(*this);
        }
        throw std::out_of_range( "Invalid variable key:[" + key + "]");
    }
};

请注意,如果您永远不需要更改 vars 字典,您可以将其转换为 static const 成员.(这意味着您需要在源文件的类外部定义和初始化它.)

Note that if you never need the vars dictionary to change, you could turn it into a static const member. (This would mean you need to define and initialize it outside the class in a source file.)

这篇关于多态成员变量指针的std :: map的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆