天天看点

Open CASCADE Foundation Classes – Basics

本章主要介绍<b>Open</b> <b>CASCADE</b>的基本功能,如内存管理(<b>memory</b> <b>management</b>)、手柄编程(<b>programming</b> <b>with</b> <b>handles</b>)、基本类型(<b>primitive</b> <b>types</b>)、异常处理(<b>exception</b> <b>handling</b>)、泛型编程(<b>genericity</b> <b>by</b> <b>downcasting</b>)、<b>Plug</b>-<b>in</b>的创建等……

一、数据类型 <b>Data</b> <b>Types</b>

1.1 基本类型 <b>Primitive</b> <b>Types</b>

基本类型是由语言定义的且他们是由值控制的。有些基本类型从类<b>Storable</b>继承而来。这就意味着他们可以在持久性对象中使用,或者被包含在对象的方法中,或者作为对象内部的一部分。由类<b>Standard</b>_<b>Storable</b>派生的类有:

l <b>Boolean</b>: 用来表示逻辑数据。只有两种状态:<b>Standard</b>_<b>True</b>和<b>Standard</b>_<b>False</b>;

l <b>Character</b>: 用来表示任意<b>ASCII</b>字符;

l <b>ExtCharacter</b>: 用来表示字符的扩展;

l <b>Integer</b>: 用来表示整数;

l <b>Real</b>: 用来表示实数;

l <b>ShortReal</b>: 用来表示实数的另一种选择,精度要低;

也有非存储类型,如:

l <b>CString</b>:

l <b>ExtString</b>:

l <b>Address</b>:

下表所示为<b>Open</b> <b>CASCADE</b>中基本类型与<b>C</b>++中基本类型对应表:

<b>C</b>++ <b>Types</b>

<b>Open</b> <b>CASCADE</b> <b>Types</b>

<b>int</b>

<b>Standard</b>_<b>Integer</b>

<b>double</b>

<b>Standard</b>_<b>Real</b>

<b>float</b>

<b>Standard</b>_<b>ShortReal</b>

<b>unsigned</b> <b>int</b>

<b>Standard</b>_<b>Boolean</b>

<b>Standard</b>_<b>False</b> = 0;

<b>Standard</b>_<b>True</b> = 1;

<b>char</b>

<b>Standard</b>_<b>Character</b>

<b>short</b>

<b>Standard</b>_<b>ExtCharacter</b>

<b>char</b>*

<b>Standard</b>_<b>CString</b>

<b>void</b>*

<b>Standard</b>_<b>Address</b>

<b>short</b>*

<b>Standard</b>_<b>ExtString</b>

Open CASCADE Foundation Classes &amp;ndash; Basics

具体请参考《<b>Open</b> <b>CASCADE</b> <b>Foundation</b> <b>Classes</b> <b>User</b>'<b>s</b> <b>Guide</b>》;

1.2 由值控制的类型

由值控制的变量类型分为三类:

l 基本类型;

l 枚举类型;

l 不是由类<b>Standard</b>_<b>Persistent</b>直接或间接派生的类;

由值控制的变量比由手柄控制的变量更直接,更快,就是不能保存到文件。

Open CASCADE Foundation Classes &amp;ndash; Basics

1.3 由引用控制的类型

由手柄控制的变量分为两类:

l 由类<b>Persistent</b>派生的类,这种类可以保存到文件;

l 由类<b>Transient</b>派生的类;

Open CASCADE Foundation Classes &amp;ndash; Basics

1.4 属性的结论

Open CASCADE Foundation Classes &amp;ndash; Basics

二、手柄编程 <b>Programming</b> <b>with</b> <b>Handles</b>

2.1 手柄定义 <b>Handle</b> <b>Definition</b>

手柄与<b>C</b>++的指针(<b>pointer</b>)类似。几个手柄可以引用同一个对象,同样地,一个手柄也可以引用了几个对象,但是一次只能是一个对象。为了访问引用的对象,必须先解除引用(<b>de</b>-<b>referenced</b>),就像使用<b>C</b>++的指针一样。临时变量和持久变量既可以是由值控制的也可以是由手柄控制的。引用非持久性对象的手柄称为不可存储手柄。因此,持久性对象不能包含不可存储手柄。

类的组织:使用手柄的类的对象可以是持久的也可是临时的。从类<b>Standard</b>_<b>Transient</b>继承的类的实例是临时的,而从类<b>Standard</b>_<b>Persistent</b>继承的类的实例是持久的。本章只讨论临时类及其相关的手柄。持久类及其相关的手柄的组织与此类似。

类<b>Standard</b>_<b>Transient</b>是<b>Open</b> <b>CASCADE</b>中由手柄控制的类层次结构中的基类。它有引用计数部分,所有的子类都继承此部分。当使用<b>Handle</b>()类时,就可知引手柄引用实例的数量。

直接或间接由类<b>Transient</b>派生的类,<b>CDL</b> <b>extractor</b>将创建类的相应的手柄<b>Handle</b>(),类名是相同的,只是在类名前加上了“<b>Handle</b>_*”。<b>Open</b> <b>CASCADE</b>提供预处理器的宏定义<b>Handle</b>(),用来产生相应类的带手柄的类。

使用手柄:在对临时对象执行任何操作之前,你必须声明手柄。如:若点(<b>Point</b>)和线(<b>Line</b>)是从包<b>Geom</b>中定义的两个临时对象,代码如下:

Open CASCADE Foundation Classes &amp;ndash; Basics

声明手柄创建了一个未指向任何对象的空手柄。手柄可以通过其方法<b>IsNull</b>()来验证。使用手柄无效,可使用方法<b>Nullify</b>()。

只要类型兼容,既可以从创建新的对象或通过赋值来初始化手柄。手柄仅用于共享的对象。对于所有的本地操作,建议使用由值控制的类。

2.2 类型管理 <b>Type</b> <b>Management</b>

<b>Open</b> <b>CASCADE</b>提供一种描述数据类型层次的通用方式,并且可以运行时检查对象类型,与<b>C</b>++的<b>RTTI</b>类似。对于从类<b>Standard</b>_<b>Transient</b>继承的每个类,<b>CDL</b> <b>extractor</b>从类<b>Standard</b>_<b>Type</b>创建代码。由类<b>Standard</b>_<b>Transient</b>派生的类的虚函数<b>DynamicType</b>()返回一个实例。通过虚函数<b>IsKind</b>()来检查给定的对象是不是指定的类型。

2.3 使用手柄创建对象 <b>Using</b> <b>Handles</b> <b>to</b> <b>Create</b> <b>Objects</b>

创建由手柄控制的对象,声明手柄并使用标准<b>C</b>++的<b>new</b>操作符,紧随其后调用构造函数。

Open CASCADE Foundation Classes &amp;ndash; Basics

与指针不同的是,手柄不需要<b>delete</b>。因为当手柄引用的对象为零时,对象将会被自动释放。

2.4 方法调用 <b>Invoking</b> <b>Methods</b>

当你使用手柄的时候,就跟使用<b>C</b>++的指针一样。调用手柄引用对象的方法使用操作符-&gt;。检查或修改手柄的状态,通过操作符点.来实现。下例所示为访问一个点对象的坐标:

Open CASCADE Foundation Classes &amp;ndash; Basics

下例所示为如何检查笛卡尔坐标点的类型:

Open CASCADE Foundation Classes &amp;ndash; Basics

当调用一个空<b>Null</b>手柄时,<b>NullObject</b>异常将会产生。

调用类方法:类方法就是<b>C</b>++类中的静态函数。即用类名加上“::”和方法名来调用。

Open CASCADE Foundation Classes &amp;ndash; Basics

2.5 手柄释放 <b>Handle</b> <b>De</b>-<b>allocation</b>

在删除一个对象之前,必须其没有被引用。为了减少管理对象生命周期的编程工作量,<b>Open</b> <b>CASCADE</b>中对象的删除函数是由手柄控制类的引用计数(<b>reference</b> <b>counter</b>)来确保。手柄就是用来管理引用计数,当对象不再引用时将会调用<b>delete</b>将其删除。当是<b>Standard</b>_<b>Transient</b>的子类时,通常不需要直接使用<b>delete</b>操作符。当对相同的对象使用<b>new</b>时,引用计数将会增加。当手柄被销毁、置为空或重新赋值,引用计数将会减少。当引用计数为0时对象将会自动调用<b>delete</b>操作符。内存分配的原理如下所示:

Open CASCADE Foundation Classes &amp;ndash; Basics

<b>Cycles</b>

本段内容不清楚,具体内容请参考原文。

2.6 不使用<b>CDL</b>创建类 <b>Creating</b> <b>Transient</b> <b>Classes</b> <b>without</b> <b>CDL</b>

尽管可用<b>CDL</b> <b>extractor</b>生成手柄类及其相关<b>C</b>++代码,然而也可不用<b>CDL</b>管理手柄。为此,在文件<b>Standard</b>_<b>DefineHandle</b>.<b>hxx</b>中提供了几个宏定义:

<b>DECLARE</b>_<b>STANDARD</b>_<b>HANDLE</b>(<b>class</b>_<b>name</b>, <b>ancestor</b>_<b>name</b>) 这个宏定义了以<b>class</b>_<b>name</b>为类名并继承类<b>ancestor</b>_<b>name</b>的手柄类。这个宏必须放在头文件中,且基类必须是可用的。

<b>IMPLEMENT</b>_<b>STANDARD</b>_<b>HANDLE</b>(<b>class</b>_<b>name</b>, <b>ancestor</b>_<b>name</b>) 这个宏实现了转换方法<b>DownCast</b>(),应该在<b>C</b>++文件中使用。

<b>DEFINE</b>_<b>STANDARD</b>_<b>RTTI</b>(<b>class</b>_<b>name</b>) 这个宏声明方法需要<b>RTTI</b>支持,应该在类的<b>public</b>中使用。

<b>IMPLEMENT</b>_<b>STANDARD</b>_<b>RTTIEXT</b>(<b>class</b>_<b>name</b>, <b>ancestor</b>_<b>name</b>) 实现上面的方法。

注:在使用这些宏的时候,必须确保参数的正确性,特别是父类的名字。否则定义将会不正确,且编译也不会报错。

Open CASCADE Foundation Classes &amp;ndash; Basics
Open CASCADE Foundation Classes &amp;ndash; Basics

三、内存管理 <b>Memory</b> <b>Management</b> <b>in</b> <b>Open</b> <b>CASCADE</b>

在几何建模的过程中,程序创建和删除相当数量的<b>C</b>++对象在动态内存中,也就是堆中(<b>heap</b>)。在这种情况下,标准函数管理内存的性能可能不足够。所以,<b>Open</b> <b>CASCADE</b>在标准包中实现了内存的管理。

3.1 用法 <b>Usage</b>

使用<b>Open</b> <b>CASCADE</b>内存管理只需要在<b>C</b>中使用<b>malloc</b>()的地方使用<b>Standard</b>::<b>Allocate</b>();在使用<b>free</b>()的地方使用<b>Standard</b>::<b>Free</b>();在使用<b>realloc</b>()的地方使用<b>Standard</b>::<b>Reallocate</b>()。

在<b>C</b>++中,类的操作符<b>new</b>()和<b>delete</b>()已经定义了在申请内存时使用<b>Standard</b>::<b>Allocate</b>()并在释放时使用<b>Standard</b>::<b>Free</b>()。所以,类所有的对象的内存都将由<b>Open</b> <b>CASCADE</b>的内存管理器来管理。

<b>CDL</b> <b>extractor</b>为所有的类定义了<b>new</b>()和<b>delete</b>()。所以,所有的<b>Open</b> <b>CASCADE</b>的类(小部分除外)都使用<b>Open</b> <b>CASCADE</b>的内存管理器。

由于操作符<b>new</b>()和<b>delete</b>()被继承,所以,所有从<b>Open</b> <b>CASCADE</b>派生的类,所有从<b>Standard</b>_<b>Transient</b>类派生的类都是由内存管理器管理。

注:若重载了部分从<b>Standard</b>_<b>Transient</b>类派生类的<b>new</b>()和<b>delete</b>(),尽管不推荐这样做,方法<b>Delete</b>()必须重定义,以便对这样的指针使用<b>delete</b>操作。这将确保合适的<b>delete</b>()函数将会被调用,即使是由手柄控制的对象。

3.2 配置内存管理器 <b>Configuring</b> <b>Memory</b> <b>Manager</b>

<b>Open</b> <b>CASCADE</b>内存管理器可以被配置以便对不同的内存区域使用不同的优化技术,或者根本不使用任何优化而直接使用<b>C</b>的<b>malloc</b>()和<b>free</b>()函数。配置方法为修改环境变量的值:

l <b>MMGT</b>_<b>OPT</b>:

l <b>MMGT</b>_<b>CLEAR</b>:

l <b>MMGT</b>_<b>CELLSIZE</b>:

l <b>MMGT</b>_<b>NBPAGES</b>:

l <b>MMGT</b>_<b>THRESHOLD</b>:

l <b>MMGT</b>_<b>REENTRANT</b>:

3.3 实现细节 <b>Implementation</b> <b>details</b>

本段内容请参考原文。

四、异常处理 <b>Exception</b> <b>Handling</b>

异常处理提供了一种从指定点转换到其他点的一种方法。一个方法可能会产生一个异常,将程序从正常执行处转换到捕捉异常处。<b>Open</b> <b>CASCADE</b>提供了异常类的层次,其基类是包<b>Standard</b>中的<b>Standard</b>_<b>Failure</b>。<b>CDL</b> <b>extractor</b>使用标准接口生成异常类。

<b>Open</b> <b>CASCADE</b>也提供将系统信号的转换成异常的支持,如数除0这样所有的情况都可以用安全、统一的方法来处理了。但是为了支持不同的平台,也使用了一些特殊的方法。

如下内容为在<b>Open</b> <b>CASCADE</b>中使用异常处理的推荐方法。

4.1 产生异常 <b>Raising</b> <b>an</b> <b>Exception</b>

类<b>C</b>++的语法:产生适当的异常将需要调用指定类型的<b>Raise</b>()方法。

Open CASCADE Foundation Classes &amp;ndash; Basics

产生了一个<b>DomainError</b>类型的异常并可附上相关信息“<b>Cannot</b> <b>cope</b> <b>with</b> <b>this</b> <b>condition</b>”,信息字符串是可选的。这个异常可以被捕捉<b>DomainError</b>类型的<b>Handler</b>捕捉到:

Open CASCADE Foundation Classes &amp;ndash; Basics

正常使用异常处理:异常不能被当作编程技巧来替代“<b>goto</b>”,但可作为防止方法被误用的一种方法。

五、<b>Plug</b>-<b>In</b>管理

六、结论

本章内容介绍了一些<b>C</b>++编程的知识及<b>Open</b> <b>CASCADE</b>对<b>C</b>++的包装。其中,手柄编程是<b>C</b>++中常见的方法,这种引用计数的方式使内存的管理更方便。

<a href="mailto:[email protected]"><b>eryar</b>@163.<b>com</b></a>

<b>Pudongxin</b> <b>Shanghai</b> <b>China</b>

<b>2012-8-23</b>

继续阅读