C++元编程思想(译)
2016-07-21 08:57
561 查看
C++ 是一种类型概念较强的语言,编译的时候都需要知道变量的类型。有时,在编译过程中,需要动态确定类型
先看一种简单的 商品信息 的存储结构;
示例code:
还可以继续扩展开来,如果有新的类似商品,这样扩展
但是对于如果业务扩张,继续销售T 恤,因为接口不能再如 getweight() 等这样了,所以就无法扩展了。
MetaClass
可以获取类型和对象的信息,并创建新的类型,类型属性,类型实例等。 MOP
关于对象的属性,结构,等就是meta 信息。 MOP就是封装 meta- level 和 object-level 。
操作主要包括:
定义个新的类型 / 添加类型的属性 / 查询类型属性/ 创建对象 / 查询对象的类型 / 设置对象的属性 / 查询对象的属性 / 删除对象
Type是为了区分出不同的属性,使用枚举变量来区分。因为有不同的value, 所以我们定义一个basevalue
通过类型创建新的value, 属性attribute 为了获取类型的名称和类型
继承的attributes 放在首位
class的主要目的就是为了创建新的对象,所以有 newObject() 返回一个指针指向对象。对于所有创建的对象,需要保存引用;如果有新的添加的属性,禁止添加到已经有实例的类中;其他方法会比较麻烦。为对象和类型维持属性列表。 属性是仅仅自己,还是包含继承该类的其他属性。对于单独的对象来说,如果可以访问到完整的属性列表是更好的。确保对于不同的类,知道它们的属性findAttribute() 搜索到属性,并返回一个引用index而 getarrtibute() 则通过index 返回相应的value。 最后的问题是什么时间添加属性:
在类的定义时候或者稍后些
传递的是值,传递handle 来实现值的传递
主要的事情就是 删除/创建,
实体对象
应用
创建 book 类型
给book 类型添加属性值
原文链接: vollmann.com/en/pubs/meta/meta/meta.html
先看一种简单的 商品信息 的存储结构;
示例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
相关文章推荐
- 基于c++或C的开源搜索引擎
- C语言字符串指针与字符数组的区别
- VC++6.0常用快捷键及对快捷键使用的看法(转)
- C 素数判断&生成素数表
- 基于C++ list中erase与remove函数的使用详解
- C语言strstr函数常用用法
- 简单利用C51的Timer0实现倒计时(F-0)
- C++中的hash_map和map的区别
- 提高项目40-带行号显示文件
- C/C++中声明与定义
- 提高项目39-电子词典
- 提高项目38-带姓名的成绩单
- VC++ 编译libcurl 支持SSL,GZIP
- boost::condition_variable 设计c++ 生产者消费者队列
- 指针变量
- 大话设计模式05----依赖倒转原则 & 里氏代换原则
- C语言代码-水题poj3781--Nth Largest Value
- C++动态数组
- C语言中体现面向对象的地方
- C++ 重载、重写、重定义