济南企业网站制作,网站上广告,wordpress 同步phpcms,wordpress如何修改用户名一个软件首先要规定能处理的数据类型#xff0c; 其次要实现三项最基本的功能——引用管理、内存管理和异常管理。在 OCC 中#xff0c;这三项功能分别对应基础类中的句柄、内存管理器和异常类。
1 数据类型 在基本概念篇里#xff0c;已经介绍了 OCC 数据类型的分类… 一个软件首先要规定能处理的数据类型 其次要实现三项最基本的功能——引用管理、内存管理和异常管理。在 OCC 中这三项功能分别对应基础类中的句柄、内存管理器和异常类。
1 数据类型 在基本概念篇里已经介绍了 OCC 数据类型的分类即依据处理方式的不同分为值处理类型和句柄处理类型两类。在详细描述这两种类型之前先描述 OCC 数据的基本类型。
1. 1 基本类型 所有基本类型都是用 CDL 预定义的并且只能通过值处理。依据不同的出自 或者依据各自的存储性能 它们可分为耐存的和非耐存的。 耐存的基本类型由 Standard_Storable 类派生 能应用于持久对象的实现要么包含于持久对象方法声明的实体中要么作为持久对象内部结构的一部分。表 3.1 给出 OCC 提供的所有基本类型和相应的 C基本类型。 下面分别论述表中的类型。
1 Standard_Integer整型。它是由 32 位二进制数表示的基本类型包括正数、 负数和零。 Integer 类型与 C int 类型一样。 因此 可以对 Integer 类型进行、 -、 *、 /四种代数运算也可以对其进行、 、 、 !、 、 六种关系运算。
2 Standard_Real实型。 它表示具有确定精度和确定范围的实数的基本类型。 Real 类型与 C 中 double双精度类型一样。因此 、 -、 *、 /四种代数运算、 -取反运算和、 、 、!、 、 六种关系运算同样适用于Real 类型。
3 Standard_ShortReal短实型。 它表示具有确定精度和确定范围的实数。ShortReal 类型与 C中 float 类型一样。 因此 、 -、 *、 /四种代数运算、 -取反运算和、 、 、 !、 、 六种关系运算同样适用于 ShortReal 类型。
4 Standard_Boolean布尔类型。 它是描述逻辑值的基本类型。 它有两种值 false 和 true。 Boolean 类型与 C中 unsigned int 类型一样。因此与、或、异或、非四种代数运算和、 !两种关系运算同样适用于 Boolean 类型。
5 Standard_Character字符类型。 它是用来表示 ASCII 字符集的一种基本类型。它能被赋予的值有 128 个对应 128 个 ASCII 字符。 Character 类型与C 中 char 类型一样。 因此 、 、 、 !、 、 六种关系运算同样适用于 Character 类型如 AB。
6 Standard_ExtCharacter扩展字符类型。它是用来表示 Unicode 字符集的一种基本类型。 由它表示的字符得用 16 位二进制数进行编码。 ExtCharacter类型与 C 中 short 类型一样。 因此 、 、 、 !、 、 六种关系运算同样适用于ExtCharacter 类型如 AB。
7 Standard_CStringC 串类型。 它用来表示文字串。 一个文字串就是由双引号括起来的一个 ASCII 字符序列。CString 类型与 C中 char*类型是一样的。
8 Standard_Address地址类型。 它用来表示一个通用指针。 Address 类型与 C中 void*类型一样。
9 Standard_ExtString扩展串类型。 它用来表示由 Unicode 字符序列构成的文字串。 ExtString 类型与 C中 short*类型一样。
1. 2 值处理类型 值处理类型可分三大类 1基本类型 2枚举类型 3由这样一些类既不是由 Standard_Persistent 类派生也不是由Standard_Transient 类派生无论是直接派生还是间接派生定义的类型。 值处理类型的表现形式比句柄处理类型的表现形式更直接。 因此 对值处理类型的操作也会更快。 但是值处理类型对象不能单独存于文件中。 图 3.1 表示了对一个值处理类型对象的处理过程。 需要注意的是 那些能被数据模式识别包括基本类型和从 Storable 类继承过来的类型的值处理类型可以作为持久对象的部分结构而存储在持久对象内部。这是值处理类型对象能够存进文件的唯一方式。
1. 3 句柄处理类型 句柄处理类型可以分为两大类
1 由 Persistent 类的派生类定义的类型。 这些类型可以被长久地存在文件中。 2由 Transient 类的派生类定义的类型。 图 3.2 表示了对一个句柄处理类型对象的处理过程。
2 句柄
2.1 句柄的定义 OCC 的引用管理采用的是一种句柄机制。这种机制的基本元素是句柄。在 OCC 中句柄是通过类实现的。句柄含有多个接口成员其中一个包含一个引用。一般情况下仅需要使用它的引用。正因为这样习惯将句柄比作C指针。 与 C指针一样 几个句柄可以引用同一个对象 一个句柄也可以引用多个对象但是每次只能引用一个在句柄访问对象前句柄必须被声明。
2.2 句柄处理类的组织 一般情况下 真正需要的是句柄引用的对象而非引用本身。 在此 有必要介绍一下句柄处理类的组织。句柄处理类要么是持久的要么是短暂的。如果由Standard_Transient 类派生则是短暂的如果由 Standard _Persistent 类派生 则 是持久的。 不论短暂还是持久 它们的组织情况是一样的。 故 下面一段文字将仅介绍短暂句柄处理类及其相关句柄的组织情况。 Standard_Transient 类是 OCC 中所有句柄处理类的一个根类另一个根类是Standard_Persistent 类。它提供了一个引用计数器被其所有后裔类继承。该计数器被 Handle()类也就是所谓的句柄 使用 用于计算指向对象实例的句柄 数。对于每一个继承直接或间接自 Transient 类的类 CDL 提取器都创建了相应的 Handle()类句柄。该 Handle()类句柄的参数名字和由“Handle_”作前缀修饰的名字一样。 OCC 专门提供了一个宏预处理函数 Handle()。 它能够将一个 Handle()类句柄的参数名字提取出来作为指定短暂类的名字。
这里提三个注意事项
1 Transient 类和 Persistent 类不完全是通过句柄处理的它们也可以通过值处理 2持久对象不能含有非耐存句柄那些引用非持久对象的句柄 3 使用句柄的目的是共享对象对于所有局部操作 建议使用值处理类。
2.3 句柄的使用 句柄通过它引用的对象被特征化。在对一个短暂对象进行任何操作之前 必须对句柄进行声明。比如 Point 和 Line 是来自 Geom 包的两个短暂类声明得像例 3.1 这样写。
例 3.1
Handle(Geom_Point) p1, p2;
Handle(Geom_Line) aLine;对一个句柄进行声明只是创建了一个空句柄该句柄不指向任何对象。 要初始化句柄 要么得创建一个新的对象 要么得将其它句柄值赋予该句柄假定两种句柄类型是兼容的。
2.4 句柄的类型管理 首先介绍句柄的通用管理。OCC 能以通用方式对数据类型进行描述。这样可以在程序运行时才去严格核对给定对象的类型。这与 C RTTI运行时类型信息机制类似。对于每一种由 Standard_Transient 类派生的类类型 CDL 提取器都创建了相应的代码段用于对 Standard_Type 类进行实例化。 通常 Standard _Type 类也称类型描述器持有类型信息类型名和其祖先类型列表。 类型的实例实际上是指向该类型的句柄由虚函数 DynamicType()该虚函数在 Standard_Transient 类的派生类中返回。检查给定对象是否具有给定类型或给定类型的后裔类型需调用另一个虚函数 IsKind()。 为给定类类型寻找相关的类型描述器 得用相关的宏 STANDARD_TYPE()。其中的宏参数就是给定类的名字。接着介绍句柄的类型一致原则。句柄声明中的对象类型是对象的静态类型 它能被编译器识别。 句柄能够引用静态类型的子类对象。 因此 对象的动态类型也称对象的实际类型 可以是静态类型的后裔类型。这就是句柄的类型一致原则。 考虑到持久类 CartesianPoint 是 Point 类的一个子类 所以 类型一致原则可以用例 3.2 表示。 例 3.2
Handle (Geom_Point) p1;
Handle (Geom_CartesianPoint) p2;
p2 new Geom_CartesianPoint;
p1 p2; //可以类型是兼容的。例子中 编译器将 p1 看做是指向 Point 类的句柄 尽管 p1 实际指向CartesianPoint 类型对象。 最后介绍句柄的直接类型转换。依据类型一致原则我们总可以将低层句柄向上赋值给高层句柄。但是 反过来则不行。因此我们需要一种直接类型转换机制。如果一个句柄所指对象的实际类型是抛掷者抛掷句柄的对象的后裔类型那么 该句柄可以直接向其子类型转换。 这就是句柄的直接类型转换见例 3.3。
例 3.3
Handle (Geom_Point) p1;
Handle (Geom_CartesianPoint) p2, p3;
p2 new Geom_CartesianPoint;
p1 p2; //可以标准的赋值。
p3 Handle (Geom_CartesianPoint) : : DownCast (p1);
// 可以 p1 的实际类型是 CartesianPoint 句柄尽管它的静态类型是 Point 句柄。如果直接转换与句柄所指对象的实际类型不兼容 那么被抛掷的句柄会被清空 并且不会产生任何异常。 因此 如果需要一些能在静态类型的子类型中实现的可靠服务如例 3.4 编写程序 例 3.4
void MyFunction (const Handle(A) a)
{
Handle (B) b Handle (B):: Downcast(a);
if (! b.IsNull())
{
//如果 B 类由 A 类派生我们就可以使用“b”。
}
else
{
// 类型不兼容。
}
}向下抛掷尤其被用于处理由不同类型对象组成的集合容器 但是有一个限制条件——这些对象必须继承自同一个根类。 例如 有一个由多个短暂对象构成的SequenceOfTransient 序列同时还有两个继承自 Standard_T- ransient 类的类 那 么例 3.5 的构造语句是有效的。
例 3.5
Handle (A) a;
Handle (B) b;
Handle (Standard_Transient) t;
SequenceOfTransient s;
a new A;
s.Append (a);
b new B;
s.Append (b);
t s.Value (1);
//这里我们不能这样写
a t;
//这是错误的。
// 因此我们向下抛掷
a Handle (A) :: Downcast (t)
if (! a.IsNull())
{
//类型兼容的话我们就可以使用 “a”。
}
else
{
// 类型不兼容。
}2.5 用句柄创建对象 要创建一个由句柄处理的对象得对句柄进行声明并用 C new 操作符初始化句柄。 这样的声明和初始化必须被构造函数的调用紧跟着 如例 3.6 所示。
例 3.6
Handle (Geom_CartesianPoint) p;
p new Geom_CartesianPoint (0, 0, 0);与 C指针不同 句柄并不支持 delete 函数。 当句柄所指对象不再被使用时该对象会被自动析构。
2.6 通过句柄调用对象方法 对于指向持久对象或短暂对象的句柄可以像使用 C指针那样使用它。 通过句柄可以调用对象方法。调用对象方法有两种方式 一是使用操作符“-” 二是使用函数调用语句。但是当需要调用方法来测试或者修改句柄状态时则必须用操作符“.”。
例 3.7 说明了怎样获取点的坐标。
例 3.7
Handle (Geom_CartesianPoint) centre;
Standard_Real x, y, z;
if (centre.IsNull())
{
centre new PGeom_CartesianPoint (0, 0, 0);
}
centre-Coord(x, y, z);例 3.8 说明了怎样获取一个笛卡尔点的类型。
例 3.8
Handle(Standard_Transient) p new Geom_CartesianPoint(0.,0.,0.);
if ( p-DynamicType() STANDARD_TYPE(Geom_CartesianPoint) )
cout Type check OK endl;
else
cout Type check FAILED endl;需要注意的是 如果指向对象方法或对象定义域的句柄是空的 那么将产生NullObject 异常。
2.7 句柄的存储分配 在删除对象前必须确保对象没有被引用。为了减少与对象生存管理有关的编程 在每个句柄处理类里都含有一个删除函数。 句柄能使引用计数管理自动进行 并且当对象不再被引用时 自动析构对象。通常不能对 Standard_Transient 类的子类实例直接调用 delete 函数。 当对象有一个新句柄时 引用计数器的值加 1。 当一个句柄被删除 或被清空 或被重新赋值而指向另一对象时 计数器的值减 1。 一旦引用计数器的值为0 时对象将被自动析构。句柄的分配规则可以通过例 3.9 体现出来。
例 3.9
...
{
Handle (TColStd_HSequenceOfInteger) H1 new TColStd_HSequenceOfInteger;
// H1 有一个引用对应的内存空间是 48 字节。
{
Handle (TColStd_HSequenceOfInteger) H2;
H2 H1;
// H1 有两个引用。
if (argc 3)
{
Handle (TColStd_HSequenceOfInteger) H3;
H3 H1;
// H1 有三个引用。
...
}
// H1 有两个引用。
}
// H1 有一个引用。
}
// H1 没有引用。
// TColStd_HSequenceOfInteger 对象被析构。如果两个或多个对象通过句柄作为定义域互相引用就会出现循环。 在这种情况下对象不会被自动析构。 以图表graph为例它的元素对象得知道它们所属的图表对象也就是说元素得有一个对图表对象的引用。如果元素和图表都是通过句柄处理的 并且都以句柄作为自己的定义域 则将出现循环。 当最后一个句柄被删除时 图标对象不会被删除。这是因为图表里面还有许多指向该图表的句柄——这些句柄作为图表的数据结构元素被存储。 有两种方式可以避免循环的出现 1用 C指针代替每一个引用比如由元素对图表的引用。 2当图表对象需要被删除时将整套句柄如元素中指向图表的句柄清空。