简体   繁体   English

C ++动态访问成员变量

[英]c++ dynamically accessing member variables

Right now I have a switch statement that takes in an input and choose one of the following actions: 现在,我有一个switch语句,它接受输入并选择以下操作之一:

Option 1 选项1

for(; i < queue_size; ++i)
{
   prepared->setString(i+1, queue.at(i).model);
}

Option 2 选项2

for(; i < queue_size; ++i)
{
   prepared->setString(i+1, queue.at(i).manufacturer);
}

Option 3 选项3

for(; i < queue_size; ++i)
{
   prepared->setString(i+1, queue.at(i).name);
}

In PHP, you would be able to do the same doing something like this: 在PHP中,您可以执行以下操作:

$queue[i][$member];

$member could then be set to "name", "manufacturer", etc. 然后可以将$ member设置为“ name”,“ manufacturer”等。

Is there any way to do something similar or more robust in C++? 有没有办法在C ++中做类似或更强大的事情?

Thanks in advance for any help/suggestions! 在此先感谢您的帮助/建议!

Using C++11 std::function or boost::function if you don't have C++11: 如果您没有C ++ 11,请使用C ++ 11 std :: functionboost :: function

std::map<YourSwitchType, std::function<void(void)> functionMap;

then define functions such as 然后定义诸如

void manufacturString() {
  for(; i < queue_size; ++i) {
    prepared->setString(i+1, queue.at(i).manufacturer);
  }
}

for each case, and populate the map with these. 针对每种情况,并在其中填充地图。

functionMap[someSwitchValue] = std::bind(&ThisType::manufactureString, this);

Then you can just call them: 然后,您可以给他们打电话:

functionMap[someSwitchValue]();

One advantage of this approach is that it doesn't limit you to member functions. 这种方法的一个优点是它不会限制您使用成员函数。 You can put non-member functions, functors, static member and non-member functions in the same map. 您可以将非成员函数,函子,静态成员和非成员函数放在同一映射中。 The only limitation is that after binding, they return void and take no arguments (that is specific to this example). 唯一的限制是绑定后,它们将返回void并且不接受任何参数(特定于此示例)。

You could do this with a map from your property names to pointer-to-member. 您可以使用从属性名称到成员指针的map进行此操作。 But it's a bit of work (you need to create that mapping yourself), and the syntax gets a bit hairy. 但这需要一些工作(您需要自己创建映射),并且语法有点冗长。 (And all the members you want to address this way must be of the same type.) (并且您要以此方式处理的所有成员都必须是同一类型。)

Demo: 演示:

#include <iostream>
#include <map>

struct Foo {
    std::string name;
    std::string address;
};

typedef std::string Foo::* FooMemPtr;
typedef std::map<std::string, FooMemPtr> propmap;

int main()
{
    propmap props;
    props["name"] = &Foo::name;
    props["address"] = &Foo::address;

    /* ... */

    Foo myfoo;
    myfoo.*(props["name"]) = "myname";
    myfoo.*(props["address"]) = "myaddress";
    std::cout << myfoo.*(props["address"]) << std::endl;
    std::cout << myfoo.*(props["name"]) << std::endl;
}

If you can use enums instead of strings, then you can access name, manufacturer, etc. indexed off of the enum values. 如果可以使用枚举代替字符串,则可以访问从枚举值索引的名称,制造商等。 It depends on how dynamic you need to be. 这取决于您需要的动态程度。

Use the STL map to perform this. 使用STL映射执行此操作。 It works as you would do in PHP. 它的工作方式与在PHP中一样。

One option is to pass an extractor functor to the function: 一种选择是将提取函子传递给该函数:

#include <string>
#include <vector>
#include <boost/bind.hpp>

struct Some {
    std::string model, manufacturer, name;
};

struct Prepared {
    void setString(size_t, std::string const&);
};

template<class Extractor>
void foo(Extractor extract) {
    Prepared* prepared = 0;
    std::vector<Some> queue;
    size_t i, queue_size = queue.size();
    for(; i < queue_size; ++i) {
        prepared->setString(i+1, extract(queue.at(i)));
    }
}

int main() {
    // C++03
    foo(boost::bind(&Some::model, _1));
    foo(boost::bind(&Some::manufacturer, _1));
    foo(boost::bind(&Some::name, _1));

    // C++11
    foo([](Some const& some){ return some.model; });
    foo([](Some const& some){ return some.manufacturer; });
    foo([](Some const& some){ return some.name; });
}

You can do this type of thing using member variable points (there are also member function pointers). 您可以使用成员变量点(也有成员函数指针)来进行此类操作。 The boost bind functions are more generic, but this is ultimately what they are doing underneath (at least in this scenario). Boost绑定函数更为通用,但这最终是它们在下面执行的操作(至少在此情况下)。

#include <iostream>
#include <string>

struct item
{
    std::string a, b;
};

//the really ugly syntax for a pointer-to-member-variable
typedef std::string item::*mem_str;

//show each member variable from the list
void show_test( item * objs, size_t len, mem_str var )
{
    for( size_t i=0; i < len; ++i )
        std::cout << objs[i].*var << std::endl;
}

int main()
{
    //create some test data
    item test[2];
    test[0].a = "A-Zero";
    test[0].b = "B-Zero";

    test[1].a = "A-One";
    test[1].b = "B-One";

    //show variables
    show_test( test, 2, &item::a );
    show_test( test, 2, &item::b );

    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM