c ++动态访问成员变量

时间:2012-05-18 07:55:53

标签: c++

现在我有一个switch语句,它接受一个输入并选择以下操作之一:

选项1

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

选项2

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

选项3

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

在PHP中,你可以做同样的事情:

$queue[i][$member];

$ member可以设置为“name”,“manufacturer”等。

有没有办法在C ++中做类似或更强大的东西?

提前感谢您的任何帮助/建议!

6 个答案:

答案 0 :(得分:4)

如果您没有C ++ 11,请使用C ++ 11 std::functionboost::function

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

然后定义诸如

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

针对每种情况,并使用这些填充地图。

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

然后你可以打电话给他们:

functionMap[someSwitchValue]();

这种方法的一个优点是它不会限制您使用成员函数。您可以将非成员函数,仿函数,静态成员和非成员函数放在同一个映射中。唯一的限制是在绑定之后,它们返回void并且不带参数(这是特定于此示例的)。

答案 1 :(得分:2)

您可以使用map从属性名称到指向成员的指针执行此操作。但它有点工作(你需要自己创建映射),语法有点毛茸茸。 (并且您希望以这种方式解决的所有成员必须属于同一类型。)

演示:

#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;
}

答案 2 :(得分:1)

如果您可以使用枚举而不是字符串,那么您可以访问从枚举值索引的名称,制造商等。这取决于你需要的动态。

答案 3 :(得分:0)

使用STL map执行此操作。它就像在PHP中一样工作。

答案 4 :(得分:0)

一个选项是将提取器仿函数传递给函数:

#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; });
}

答案 5 :(得分:0)

你可以使用成员变量点来做这种事情(也有成员函数指针)。 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;
}