您的位置:首页 > 编程语言 > C语言/C++

Metaclasses and Reflection in C++

2012-03-05 12:53 459 查看

Introduction

C++ is a strongly typed compiler language. Though not as strongly typed as ADA, a C++ compiler will complain if you try to assign an object of one type to an object of another type (if there is no acceptable conversion). Obviously, this requires that the compiler knows all available types. More specifically, all classes must be known at compile-time1. But sometimes, it would be quite handy to add new classes at runtime. And in some application domains, this is absolutely necessary.

A simple story

Let's look at a simple example: Susan, the manager of a local bookstore, wants to expand into the Internet. So she asks you to write a simple program for an Internet bookshop. No problem for you. Part of your solution will probably look like the class model in Fig. 1.

Object Class

class Object
{
public:
explicit Object(ClassDef const * class_)
: myClass(class_), values(class_->getAttributeCount())
{
buildValueList();
}

ClassDef const & instanceOf() const
{
return *myClass;
}

Value getValue(size_t attribIdx) const
{
return *values[attribIdx]; // calls Value(BaseValue &)
}
Value getValue(string const & attribName) const
{
size_t idx = instanceOf()->findAttribute(attribName);
// should check for not found
return getValue(idx);
}

void setValue(size_t idx, Value const & v)
{
values[idx]->set(v);
}
void setValue(string const & attribName, Value const &v)
{
size_t idx = instanceOf()->findAttribute(attribName);
// should check for not found
setValue(idx, v);
}

private:
typedef vector<BaseValue *> ValueContainer;
void buildValueList()
{
ClassDef::AttrIterator a;
ValueContainer::iterator i = values.begin();
for (a = instanceOf()->attribBegin();
a != instanceOf()->attribEnd();
++a, ++i)
{
*i = a->getType().newValue();
}
}

ClassDef const * const myClass;
ValueContainer values;
};


Now the MOP is complete. Let's use it:
Creating the
Product
class:

ClassDef * product
= new ClassDef(0, // no base class for Product
"Product"); // name of class


Adding attributes:

product->addAttribute(Attribute("Product Number", Type::intT));
product->addAttribute(Attribute("Name", Type::stringT));
product->addAttribute(Attribute("Price", Type::doubleT));
product->addAttribute(Attribute("Weight", Type::doubleT));


Creating the
Book
class with an attribute list:

list<Attribute> attrL;
attrL.push_back(Attribute("Author", Type::stringT));
attrL.push_back(Attribute("Title", Type::stringT));
attrL.push_back(Attribute("ISBN", Type::intT));

ClassDef * book
= new ClassDef(product, // base class
"Book",
attrL.begin(), attrL.end());


Creating an object:

Object * bscpp(book->newObject());


Setting the values for the objects:

Set an int value by index (don't forget that index 0 is
ProductNo
):

bscpp->setValue(0, RealValue<int>(12345));


Same for a string value:

bscpp->setValue(4, RealValue<string>("Bjarne Stroustrup"));


Better way: set value by name this gives the most derived attribute:

bscpp->setValue("Title",
RealValue<string>("The C++ Programming Language"));
bscpp->setValue("Weight", Value<double>(370));


Getting the values:

Display a book:

ClassDef::AttrIterator a;
size_t idx;
for (a = book->attribBegin(), idx = 0;
a != book->attribEnd();
++a, ++idx)
{
cout << a->getName() << ": "
<< bscpp->getValue(idx).asString() << endl;
}


and we get:

Product Number: 12345
Name:
Price:
Weight: 370
Author: Bjarne Stroustrup
Title: The C++ Programming Language
ISBN:


So, our MOP is complete. For our sample application, you have to add a class repository, some nice GUI to define classes and objects, creating the index for the search machine, provide an interface for
ShoppingCart
, but then you're done, and Susan is happy as she now can create her own new product categories at runtime.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: