C++元编程思想(译)

来源:互联网 发布:淘宝店铺长时间不用 编辑:程序博客网 时间:2024/05/16 10:40

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 derivedAtrtibuteContainer::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

0 0
原创粉丝点击