C++ 元类






2.60/5 (4投票s)
1999年12月1日
2分钟阅读

77638

1044
可在运行时修改的类
引言
这是一个用 C++ 实现的简单元类仿真。元类是一个类的类,即这个类的对象本身可以充当类。因此,用户可以在运行时添加或删除属性。
我正在进行的一个项目需要一个类似于这个类的功能。首先,我们设计一个类(例如具有 x、y 和 z 属性),供用户使用。但是,非常进取的用户希望向这个类添加更多数据供他/她和其他人使用。因此,他添加了属性 a 和 b 到这个类,现在它具有 x、y、z、a 和 b 作为其属性。这个用户所做的新增内容将仅供他使用,除非他或管理员授予其他有要求的用户的权限。该类的管理员有权向其添加属性,因此使用静态函数。
所以即使类是相同的,它的可见性对于不同的用户和应用程序也是不同的。因此它可以用于不同的用途。在我编写的类中,仅使用了一个 TCHAR
。用户可以使用列表,或者根据他/她的需要使用任何东西。
因此,该类适用于用户应该能够在运行时添加新属性的地方;-- 一个用户定义的类,但在运行时。
C++ 本身并不直接支持这种机制,就像 Smalltalk 和 CLOS 中一样。但是,它可以使用其静态数据和函数成员在 C++ 中实现。
此程序实现了一个名为 MetaVec
的元类。MetaVec
的静态数据和函数在其实例化之前就存在。因此,可以从“外部”向其添加一个属性,在本例中是一个字符串数组。
添加到这个类的属性对它的所有成员都可用。其想法是限制对这个类的对象访问这些属性。此权限是通过为每个对象分配特定的索引来指定的。这些索引对应于链表 PtrVec
中的值(属性)。例如,如果列表有 7 个名称,并且对象 A
仅被分配了索引 0、1 和 3,那么它只能访问链表中位于这些索引位置的那些名称。
因此,这个类的许多对象都可以拥有不同的属性;一种用户定义的类,在运行时。
这个元类的演示版本使用字符串值作为属性。用户可以使用链表作为静态容器对象。PtrVec
是一个 STL 模板,可以包含任何类型的对象。
// MetaVec class definition typedef vectorPtrVec; // container object typedef PtrVec::iterator itPtrVec; typedef vectorListIndex; typedef ListIndex::iterator itListIndex; typedef long INDEX; typedef long ATTRIBUTE_NO; typedef long NO_OF_ATTRIBUTES; typedef ListIndex LIST_INDEX; class MetaVec { private: // identifer of this object int iClsID; // total count of classes for assigining ClsIDs automatically static int ClsCount; // list of indices for attributes // that are permitted fot this object ListIndex Index; // for locking the object. New attributes // can be added but cannot be used bool ObjectLock; // list of attributes for the metaclass ie all objects static PtrVec VecObject; public: MetaVec(bool LockStatus = false); ~MetaVec(); // Adds a new attributes to the metaclass - in the list of names static long AddAttribute(TCHAR* Name); // This assignes an index to an object // to decide the permissions that object has on // the attributes of the metaclass. Any object can // access only those attributes that // are assigned to it bool AssignIndex(ListIndex LstIndex); // overloaded to receive a single value bool AssignIndex(int iIndex); // removes the assigned index and // returns the removed index -- overloaded INDEX RevokeIndex(int iIndex); // removes a list of assigned indexes and returns the removed list LIST_INDEX RevokeIndex(ListIndex IndexList); // this lists all the available attributes and their IDs static NO_OF_ATTRIBUTES ListAllAttributes(); // Queries an object for its properties - Class ID, Index and Name void QueryObject(); // locks the object so that no new indices can be assigned to it // toggles between locked and un-locked bool LockObject(bool LockState = true); // checking the lock status of an object bool CheckLockStatus(); };