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

C++元编程思想(译)

2016-07-21 08:57 561 查看
C++ 是一种类型概念较强的语言,编译的时候都需要知道变量的类型。有时,在编译过程中,需要动态确定类型

先看一种简单的 商品信息 的存储结构;



示例code:

class Book
{
public:
Book(const string & author_,
const string & title_,
const string & publisher_,
double price_,
double weight_);
string getName()
{
string name;
name = author + ": " + title;
return name.substr(0, 40);
}
double getPrice();
double getWeight();
private:
string author, title, publisher;
double price, weight;
};


还可以继续扩展开来,如果有新的类似商品,这样扩展



但是对于如果业务扩张,继续销售T 恤,因为接口不能再如 getweight() 等这样了,所以就无法扩展了。

MetaClass 

可以获取类型和对象的信息,并创建新的类型,类型属性,类型实例等。 MOP

关于对象的属性,结构,等就是meta 信息。  MOP就是封装 meta- level 和 object-level 。



操作主要包括:

定义个新的类型 / 添加类型的属性 / 查询类型属性/  创建对象 / 查询对象的类型 / 设置对象的属性 / 查询对象的属性 / 删除对象



Type是为了区分出不同的属性,使用枚举变量来区分。因为有不同的value, 所以我们定义一个basevalue

calss Type
{
public:
enum Type T{stringT , int T, double T, unknown T};
explicit Type(Type T typeId_): typeId(typeId_){}
BaseValue * newValue() const
{
return prototypes[typeId]->clone();
}
TypeT getType() const
{
return typeId;
}
static void int();
{
prototypes[stringT] = new Value<string>("");
prototypes[intT] = new Value<int>(0);
prototypes[double T] = new Value<double>(0);
}
private:
TypeT typeId;
static vector<BaseValue *>prototypes;
}
vector<BaseValue*>Type::prototypes(Type::unknownT);


通过类型创建新的value, 属性attribute 为了获取类型的名称和类型

class Attribute
{
public:
Attibute(const string &name_, Type:: TypeT typeId)
:name(name_),type_(typeID)
{}
const string & getName() const
{
return name;
}
Type getType() const
{
return type_;
}
private:
string name;
Type type_;
};

继承的attributes 放在首位

class的主要目的就是为了创建新的对象,所以有 newObject() 返回一个指针指向对象。对于所有创建的对象,需要保存引用;如果有新的添加的属性,禁止添加到已经有实例的类中;其他方法会比较麻烦。为对象和类型维持属性列表。 属性是仅仅自己,还是包含继承该类的其他属性。对于单独的对象来说,如果可以访问到完整的属性列表是更好的。确保对于不同的类,知道它们的属性findAttribute() 搜索到属性,并返回一个引用index而 getarrtibute() 则通过index 返回相应的value。 最后的问题是什么时间添加属性:
在类的定义时候或者稍后些

class ClassDef
{   //typedefs Container, Iterator for attributes
public:
ClassDef(ClassDef const *base, const string &name_)
:baseClass(base), name(name_),
definitionFix(false)
{
baseInit();
effectiveAttributes.insert(effectiveAttributes.end(),
ownAttibutes.begin(),
ownAttributes.end());
}
template<typename iterator>
ClassDef(ClassDef const * base, const string name_, iterator attribBegin, iterator attibEnd)
: baseClass(base), name(name_),
ownAttributes(attriBegin, attribEnd),
definitionFix(false)
{
baseInit();
effectiveAttributes.insert(effectiveAttributes.end(),
ownAtttibutes.Begin(),
ownAttributes.end());
}
string getName() const;
Object * newObject() const
{
definitionFix = true;
return new Object(this);
}
AtttIterator attribBegin() const;
AttrIterator attriEnd() const;
AttrIterator const & getAttribute(size_t idx) const;
void addAttribute(const Attribute&);
size_t getAttributeCount() const;

size_t findAttribute(string const & name) const
{
// this does a reverse search to find the most derived
AtrtibuteContainer::const_reverse_iterator i;

for(i = effectiveAttributes.rbegin();
i != effectiveArributes.rend();
++i)
{
if(i->getName() = name)
{
return distance(i, effectiveAttributes.rend()) - 1;
}
}
return getAttributeCount();
}
private:
void baseInit()
{
if(baseClass)
{
baseClass->definitionFix = true;
copy(baseClass->attribBegin(), baseClass->attribEnd(), back_inserter<AttributeContainer>(effectiveAttributes));
}
}
ClassDef const * const baseClass;
string name;
AttributeContainer ownAttributes, effectiveAttributes;
mutable bool definitionFix;
}

传递的是值,传递handle 来实现值的传递

Value BaseValue::get()
{
return *this;  // call Value(BaseValue const &)
}

class BaseValue
{
public:
virtual ~BaseValue() {}
virtual BaseValue * clone() const = 0;
virtual string asString() const = 0;
// fromString()

virtual void set(Value const &v) = 0;
// no get()!

private:
//Type info
};
需要有 int, double, strring 等类型, 这种很容易让人想到使用模板

template <typename PlainT>
class RealValue : public BaseValue
{
public:
RealValue(PlainT v)
: val(v) {}

RealValue * clone() const
{
return new RealValue(*this);
}

string asString() const
{
ostringstream os;
os << val;
return os.str();
}

operator PlainT() const // conversion to plain type
{
return val;
}

RealValue<PlainT>::set(Value const & v)
{
val = v.get<PlainT>();
}

private:
PlainT val;
};


主要的事情就是 删除/创建,

class Value        // Value handle
{
public:
Value(BaseValue const & bv)
: v(bv.clone())
{}

Value(Value const & rhs)
: v(rhs.v ? rhs.v->clone() : 0)
{}

explicit Value(BaseValue * bv = 0)
: v(bv)
{}

~Value()
{
delete v;
}

Value & operator=(const Value & rhs)
{
// this is not a typical pimpl assignment, but a set()
if (v)
{
if (rhs.v)
{ // fine, all v's exist
v->set(rhs);
}
else
{ // the other v doesn't exist, so we must delete our own :-(
BaseValue * old = v;
v = 0;
delete old;
}
}
else
{ // we don't have a v, so just copy the other
v = (rhs.v ? rhs.v->clone() : 0);
}

return *this;
}

template <typename PlainT>
PlainT get() const
{
if (v)
{
RealValue<PlainT> const & rv
= dynamic_cast<RealValue<PlainT> const &>(*v);
return rv;        // uses conversion operator
}
else
{
return PlainT();
}
}

std::string asString() const
{
if (v)
{
return v->asString();
}
else
{
return string();
}
}

private:
BaseValue * v;
};


实体对象

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

应用

创建 book 类型

ClassDef base(0, "Product", 0,
Product::ownAttribBegin(),
Product::ownAttribEnd());
ClassDef book(makeClass<Book>(&base, "Book"));

给book 类型添加属性值

Object * ecpp(book.newObject());

ecpp->setValue(5, RealValue<double>(22.50));
ecpp->setValue(0, RealValue<int>(23456));
ecpp->setValue(2, RealValue<string>("Scott Meyers"));
ecpp->setValue("Title", RealValue<string>("Effective C++"));
ecpp->setValue(6, RealValue<double>(280));
size_t idx;

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

cout << ecpp->getValue("Author").asString() << endl;


原文链接: vollmann.com/en/pubs/meta/meta/meta.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: