如何遍历类中的所有成员?

时间:2010-12-16 07:31:54

标签: c++


假设我有一个班级

class CAT  
{  
private:  
  int a;  
  long b;  
  double c;    
  string d;  
};    

现在我需要一个可以将所有成员初始化为特定值的函数,例如:

  • int设置为0
  • 长设为-1
  • 双设置为-1.1
  • 字符串设置为未知

到目前为止,我可以编写一个名为initMembers的函数:

void initMembers()   
{   
    a = 0;   
    b = -1;   
    c = -1.1;   
    d = "unknown";   
}   

但如果我有像CAT这样的1000个类,其中一些有4个成员,其中一些有40个成员,.....所以我必须为每个班级写一个initMember功能。

我想知道是否有办法可以遍历一个班级内的所有成员?

感谢您的帮助!

我的意思是我想用相应的值初始化特定类型

适用于所有类中的所有成员

* int set to 0
* long set to -1
* double set to -1.1
* string set to unknown

6 个答案:

答案 0 :(得分:3)

我可以建议你一本C ++书吗?我想你错过了一些关于这种语言的基本知识。

  1. 您只能拥有名为CAT的一个类,而不是数千个。你可以拥有数以千计的实例,这是完全不同的事情。

  2. 您使用类构造函数来执行您在initMembers()函数中执行的操作:

    class CAT  
    {  
    public:  
        CAT(): a(0), b(-1), c(-1.1), d("unknown") { }
    
    
    private:  
      int a;  
      long b;  
      double c;    
      string d;  
    }; 
    
  3. C ++没有反射,因此没有办法“遍历”其成员。

答案 1 :(得分:2)

没有。 C ++没有反射。

答案 2 :(得分:2)

了解Boost.Fusion可以做些什么:

#include <iostream>
#include <string>

#include <boost/fusion/adapted/struct/define_struct.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/lambda/lambda.hpp>

BOOST_FUSION_DEFINE_STRUCT
(
    /* namespace */,
    CAT,
    (int, a)
    (long, b)
    (double, c)
    (std::string, d)
)

struct initializer
{
    void operator()(int &v) const { v = 1; }
    void operator()(long &v) const { v = -1; }
    void operator()(double &v) const { v = 1.1; }
    void operator()(std::string &v) const { v = "unknown"; }
};

int main() 
{
    CAT c;
    boost::fusion::for_each(c, initializer());
    boost::fusion::for_each(c, std::cout << boost::lambda::_1 << ' ');
    std::cout << std::endl;
}

输出:

1 -1 1.1 unknown

答案 3 :(得分:2)

正如所有答案所说,C ++中没有任何反映。如果你有1000个独特的类(不是实例),那么必须编写相同的样板代码(例如ctors / dtors,可能是流操作等)是痛苦的。

当我面对这样的事情时,我总是退后一步。首先,我创建一个包含所有结构的xml文档,而不是蒸头并写出所有C ++代码,例如,假设我有两个结构,我将创建类似的东西:

<classet>
<struct name="some_struct_a">
  <field type="int" name="foo"/>
  <field type="int" name="foo2"/>
  <field type="long" name="bar"/>
  <field type="std::string" name="bar2"/>
</struct>
<struct name="some_struct_b">
  <field type="int" name="foo"/>
  <field type="int" name="foo2"/>
</struct>
</classet>

一旦完成,我创建一个xslt(你不需要成为xsl的下一级大师来做这件事),从上面的xml生成C ++代码。因此,如果您需要为所有类添加任何方法,例如,修改xsl并重新生成,修改任何结构,修改xml和重新生成也是如此。准备好xml和xslt后,更改周期非常快。

顺便说一下。在你嘲笑之前,很多交易所(金融)都提供了描述消息格式的xml文档,原因很简单,其中一些在xml中定义了大量的消息,有些则有非常多的成员。

答案 4 :(得分:1)

我们在代码中使用hack来自动初始化代码中的数据成员:

#define member(type, name, initval)
class class_ ## name { \
  type data;
  inline class_ ## name() : data(initval) {};\
  inline type operator()() const { return data; };\
  inline void operator(type newval) { data=newval; };\
};

然后,在任何一个班级:

class CAT {
  private:  
  member(int, a, 0);  
  member(long, b, -1);  
  member(double, c, -1.1);    
  member(string, d, "unknown"); 
  void foo() {
    d("newstring");  // set
    int aval=a();  // access
  };
};

您可以调整上面的宏并添加一些其他整洁的功能。但是,对于现有代码,这意味着需要进行一些重组/重写。

答案 5 :(得分:0)

您可能希望构建一个源代码生成工具,该工具将一些有关您需要的类的数据文档转换为C ++类声明代码。 例如。如果你想为每只动物准备一个课程并且你有一些关于这些动物的数字文献,可以创建一个定制的工具来解析动物书籍,过滤动物名称并从中创建类样板代码。