二、Agent类:用C++指针模拟JAVA对象
为了更好的说明C++与JAVA的相似之处,笔者建立了Agent类。它通过把一个特定对象类型的指针作为自己的保护成员,来实现对C++指针的包装。
任何使用Agent类模拟JAVA的程序必须通过如下表所示的方法来使用对象:
表2
操作 | JAVA | 使用Agent后的C++ | 声明 | ObjectClass Instance | Agent<ObjectClass> Instance | 创建 | Instance=new ObjectClass() | Instance=new Agent<ObjectClass> | 数据访问 | Instance.Data | Instance().Data | 方法调用 | Instance.Method() | Instance().Method() | 复制 | 指针复制 | Instance1=Instance2 | 内容复制 | 由类自身定义 | 比较 | 指针比较 | Instance1==Instance2 | 内容比较 | 由类自身定义 | 销毁 | 不需要,由程序内部自动管理 |
上表显示了两种对象在使用上的惊人的相似性。本质上,两种对象是一样的,因为JAVA解释器本身就是使用与Agent相似的实现方法。但有些形式上的相似性事实上是无法做到的,因为它们毕竟属于两种不同的语言,必须依照各自的规定。以下是两种需要注意的形式上的差别:在C++中,
1、 象所属类的名称(如ObjectClass)必须放在Agent后,用〈 〉包括起来(否则,该类将与本文所讨论的Agent类毫无关系);
2、 对象本身数据的访问和方法的调用必须在对象表识符后加一对括号,如Instance().Method(),因为Agent重定义了操作符operator (),以帮助编译器将一个Agent的实例(如Instance)解释成用户所使用的具体某一个类(如ObjectClass)的实例,而Instance().Method()这一调用本身也等价于((ObjectClass&)Instance).Method()。
另外,任一使用了Agent的程序必须在首部加入#include "Agent.h"才能实现对它的访问。
以下为包含类Agent全部定义的C++头文件。由于该文件篇幅较小,所有Agent的方法均采用内联函数的形式定义。
#ifndef OBJECT_AGENT_CLASS #define OBJECT_AGENT_CLASS
#define null 0
template<class ObjectType> class Agent { int *Reference; static bool bNewOperation;
protected:
ObjectType *Marrow; void Finalize() { if (Reference) { (*Reference)--; if (Marrow) { if (*Reference<=0 && Marrow) { delete Marrow; delete Reference; } Marrow=null; } Reference=null; } }
public:
// constructors Agent() { if (bNewOperation) { Marrow=new ObjectType; Reference=new int; *Reference=1; bNewOperation=false; } else { Marrow=null; Reference=null; } }
Agent(ObjectType obj) { Marrow=new ObjectType; Reference=new int; *Reference=1; *Marrow=obj; }
// destructor ~Agent() { Finalize(); }
// convertions operator ObjectType&() { return *Marrow; }
// operators Agent<ObjectType>& operator=(Agent<ObjectType> obj) { Finalize(); Marrow=obj.Marrow; Reference=obj.Reference; (*Reference)++; return *this; }
Agent<ObjectType>& operator=(Agent<ObjectType>* obj) { Finalize(); if (obj) { Marrow=obj->Marrow; Reference=obj->Reference; } return *this; }
bool operator ==(Agent<ObjectType> obj) const { return Marrow==obj.Marrow; }
bool operator !=(Agent<ObjectType> obj) const { return Marrow!=obj.Marrow; }
ObjectType& operator ()() { return *Marrow; }
void *operator new(size_t size) { bNewOperation=true; return new char[size]; } };
template<class ObjectType> bool Agent<ObjectType>::bNewOperation=false;
#endif
|
从源程序中可以看出,Agent类实际上是一个模版(template)。这样做的好处是,用户不必为包容自己不同类型的对象而定义之相对应的Agent类。
Agent类的工作原理是这样的:
当用户使用Agent<ObjectClass>来定义对象的类型时,他事实上定义的是一个Agent类型的对象。编译器自动为该对象产生一个类型为ObjectClass*,名为Marrow的成员,而ObjectClass* Agent::Marrow才真正代表用户将要建立的对象。整型成员Reference记录当前对此对象的Marrow的引用个数,当降为0时自动消除Marrow,即销毁用户定义的ObjectClass实例。当用户调用Instance=new Agent<ObjectClass>来创建对象时,分配Marrow,Reference置1,对象处于可使用状态。两个Agent实例互相赋值时,重定义的操作符operator =协助复制Marrow指针,更改公共的Reference成员,使之指示正确的引用计数。还有一个必须注意的静态成员:bNewOperation。它是一个布尔(真假值)类型的变量。当程序员用Agent<ObjectClass> Instance来定义对象时,其值为false,指出不需要真正建立Agent::Marrow的实例,因而Marrow将被赋值为null;当用Instance=new Agent<ObjectClass>来创建对象实例时,其值为true,提示构造函数建立相应Marrow的实例。其控制通过操作符operator new实现。而操作符operator ()则使得,当调用Instance()时,编译器自动返回ObjectClass类型的*Marrow,所以调用用户所需的对象成员可以使用Instance().Data和Instance().Method()。 
2/2 首页 上一页 1 2 |