class CAT
{
private:
int a;
long b;
double c;
string d;
};
now I need a function which can initialize all the members to a specific value, for example:
- int set to 0
- long set to -1
- double set to -1.1
- string set to unknown
so far, I can write a function named initMembers:
void initMembers()
{
a = 0;
b = -1;
c = -1.1;
d = "unknown";
}
but if I have 1000 classes like CAT, and some of them have 4 members, some of them have 40 members,..... so I have to write an initMember functuions for every class.
I wonder if there is way can traversed all the members inside a class?
Thanks advance for your help!
I mean I want initialize specific type with a corresponding value
for all members inside all classes
* 开发者_开发问答int set to 0
* long set to -1
* double set to -1.1
* string set to unknown
No. C++ doesn't have reflection.
May I suggest you a C++ book? I think you are missing some basic about this language.
you can only have one class named CAT, not thousands of them. You can have thousands of instances of it, that's a whole different thing.
You use class constructors to do what you are doing in
initMembers()
function:class CAT { public: CAT(): a(0), b(-1), c(-1.1), d("unknown") { } private: int a; long b; double c; string d; };
C++ doesn't have reflection, so there's no way to "traverse" its members.
Just an idea of what can be done with 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;
}
Outputs :
1 -1 1.1 unknown
As all answers have said, there is no reflection in C++. And if you have 1000s of unique classes (not instances), then it's painful to have to write the same boiler plate code (such as ctors/dtors, may be streaming operations etc.)
When I face something like this, I always take a step back. First, rather than steaming a head and writing out all the C++ code for each class, I create an xml document which has all the structures, for example, let's say I have two structs, I'll create something like:
<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>
Once that's done, I create an xslt (and you don't need to be a next level guru at xsl to do this), to generate the C++ code from the above xml. So, if you ever need to add any method to all your classes for example, you modify the xsl and re-generate, same goes for modifying any of the structures, modify the xml and re-generate. Once you get the xml and xslt ready, the change cycle is very quick.
Btw. before you scoff, lot's of exchanges (financial) provide xml documents describing message formats for this exact reason, some of these define a large number of messages in xml, and some have very large number of members.
We use a hack in our code to auto-initialize data members in the code:
#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; };\
};
And then, in any class:
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
};
};
You can tune the above macro and add some other neat functionality. However, for existing code, this means some amount of restructuring/rewrite.
You probably want to build an source code generation tool which translates some data document about what classes you need into C++ class declaration code. E.g. if you want to have a class for every animal and you have some digital literature about the animals, create a tailored tool to parse the animal book, filter the animal names and create class boilerplate code from it.
精彩评论