OpenCASCADE开发指南<四>: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 类型(如: A<B)。

(6) Standard_ExtCharacter(扩展字符类型)。它是用来表示 Unicode 字符集的一种基本类型。 由它表示的字符得用 16 位二进制数进行编码。 ExtCharacter类型与 C++ 中 short 类型一样。 因此, <、 <=、 ==、 !=、 >=、 >六种关系运算同样适用于ExtCharacter 类型(如: A<B)。

(7) Standard_CString(C 串类型)。 它用来表示文字串。 一个文字串就是由双引号括起来的一个 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.3Handle (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)当图表对象需要被删除时,将整套句柄(如元素中指向图表的句柄)清空。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/741866.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mysql 学习(十七)事务隔离级别和MVCC

前提准备 首先创建一个表&#xff1a; CREATE TABLE hero (number INT,name VARCHAR(100),country varchar(100),PRIMARY KEY (number) ) EngineInnoDB CHARSETutf8;INSERT INTO hero VALUES(1, 刘备, 蜀);事务隔离级别 mysql 是一个 客户端 和 服务器架构的软件&#xff0c…

【数据结构】详解线性表的各个函数接口+OJ习题讲解(画图比写代码更重要!!!)

文章目录 一、线性表二、顺序表1、什么是顺序表2、顺序表的分类 三、动态顺序表的实现1、结构的定义2、顺序表的初始化3、检查容量4、在头部插入数据5、在尾部插入数据6、在指定位置插入数据7、在尾部删除数据8、在头部删除数据9、删除指定位置的数据10、查找数据11、修改指定位…

ThreeJs制作模型图片

这个标题名字可能有歧义&#xff0c;只是不知道如何更好的表达&#xff0c;总之就是将图片的像素转换成3D场景的模型&#xff0c;并设置这个模型的颜色&#xff0c;放到像素点对应的位置从而拼接成一个图片&#xff0c;起因是上文中用js分解了音乐&#xff0c;实现了模型跳动效…

互联网行业的应届大学生,如何制作高水平简历?

雇主通常只会花大约25秒的时间浏览一份简历,因此,拥有一份出色的简历对于找到理想工作至关重要。如果您的简历没有令人印象深刻的特点,那么如何才能在竞争激烈的求职市场中脱颖而出呢? 如果您不知道如何在简历上有效地展示自己,或者觉得简历无论怎么修改都不够突出,那么请…

安装、配置MySQL

安装相关软件 MySQL Server、MySQL Workbench MySQL Server&#xff1a;专门用来提供数据存储和服务的软件 MySQL Workbench&#xff1a;可视化的 MySQL 管理工具 官网安装 https://www.mysql.com/ 官网 MySQL :: Download MySQL Installer 安装包路径 在这里选择版本和和对应…

多图如何导入多个二维码?图片批量导出二维码的技巧

多个图片分别生成对应的二维码怎么做&#xff1f;现在扫码看图片是一种很常用的内容预览方式&#xff0c;有些产品包装也会采用这种方式来展示对应的信息&#xff0c;怎么简单快速的将图片生成二维码&#xff0c;相信有很多的小伙伴都非常的感兴趣。那么小编通过下面这篇文章来…

探索C++中的动态数组:实现自己的Vector容器

&#x1f389;个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名乐于分享在学习道路上收获的大二在校生 &#x1f648;个人主页&#x1f389;&#xff1a;GOTXX &#x1f43c;个人WeChat&#xff1a;ILXOXVJE &#x1f43c;本文由GOTXX原创&#xff0c;首发CSDN&…

echarts line绘制机组开关状态折线图

2024.3.12今天我学习了如何用echarts line实现设备开关状态的效果。 代码如下&#xff1a; option {xAxis: {type: time,},yAxis: {type: value,splitNumber:2,// axisLine: {// show: true,// lineStyle: {// color:#808080// }// },axisLabel:{formatt…

管控员工上网行为(让老板管理更省心更高效)

很多老板都有这样一种顾虑&#xff1a; 员工到底有没有认真工作&#xff0c;工作是不是做到了全身心投入。 为什么会有担心员工工作状态的问题发生&#xff1f; 无疑是员工在上班时间浏览与工作无关的网站、下载私人文件、甚至是泄露公司机密等行为&#xff0c;让老板不放心了…

Elasticsearch:在本地使用 Gemma LLM 对私人数据进行问答

在本笔记本中&#xff0c;我们的目标是利用 Google 的 Gemma 模型开发 RAG 系统。 我们将使用 Elastic 的 ELSER 模型生成向量并将其存储在 Elasticsearch 中。 此外&#xff0c;我们将探索语义检索技术&#xff0c;并将最热门的搜索结果作为 Gemma 模型的上下文窗口呈现。 此外…

岭回归:优化预测的利器

在数据科学和机器学习的领域&#xff0c;构建准确、稳定的预测模型是一项至关重要的任务。岭回归作为一种强大的工具&#xff0c;被设计用来应对数据集中存在多重共线性的问题&#xff0c;并通过引入正则化来缩小预测误差。 1. 岭回归的原理&#xff1a; 岭回归是线性回归的一…

【国产】API接口管理平台的产品设计与搭建讲解

【国产接口管理平台】PhalApi Pro (π框架专业版) PhalApi Pro (发音&#xff1a;π框架专业版)&#xff0c;是一款国产企业级API接口管理平台&#xff0c;可以零代码、快速搭建API接口开发平台、接口开放平台、接口管理平台。基于PhalApi开源接口开发框架&#xff0c;通过低代…

【gpt实践】李某的AI课程值199吗

先说个人的答案&#xff1a;不值。但也不是说毫无价值&#xff0c;只是他的价值没那么高。 文末分享该课程&#xff0c;大家有兴趣可以看看&#xff0c;该课程是否有价值。 “清华博士”推出的199元的AI课程销售额竟然突破了5000万。这一数字让人惊叹&#xff0c;也引发了人们…

亚马逊、速卖通卖家如何做好测评让店铺销量稳定增长?

近期有刚入驻跨境电商的新买家咨询珑哥&#xff0c;店铺上的产品有人浏览&#xff0c;就是没有人下单&#xff0c;新店铺很正常因为很多人去购买东西&#xff0c;首先看的是评价&#xff0c;没有评价一般人不敢直接去下单。就像我们去淘宝买东西&#xff0c;都要看下评价&#…

测试用例的设计(2)

目录 1.前言 2.正交排列(正交表) 2.1什么是正交表 2.2正交表的例子 2.3正交表的两个重要性质 3.如何构造一个正交表 3.1下载工具 3.1构造前提 4.场景设计法 5.错误猜测法 1.前言 我们在前面的文章里讲了测试用例的几种设计方法,分别是等价类发,把测试例子划分成不同的类…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:Web)上篇

提供具有网页显示能力的Web组件&#xff0c;ohos.web.webview提供web控制能力。 说明&#xff1a; 该组件从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。示例效果请以真机运行为准&#xff0c;当前IDE预览器不支持。 需要权…

Java项目:基于springboot实现的OA协同办公系统(源码+数据库+毕业论文)

一、项目简介 本项目是一套基于Springbootvue实现的付费自习室系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、…

从零开始利用MATLAB进行FPGA设计(一):建立脉冲检测模型的Simulink模型2

目录 1.模块的总体结构 1.1从工作空间导入输入信号 1.2FIR滤波器 2.Subsystem 3.MATLAB Function 文章灵感来源于MATLAB官方免费教程&#xff1a;HDL Coder Self-Guided Tutorial 考虑到MATLAB官网的英文看着慢&#xff0c;再加上视频讲解老印浓浓的咖喱味&#xff0c;我…

【CSP】2021-12-2 序列查询新解 分段处理 用乘法代替加法减少时间复杂度(思想是离散化)

2021-12-2 序列查询新解 分段处理 用乘法代替加法减少时间复杂度&#xff08;思想是离散化&#xff09;2021-12-2 序列查询新解 分段处理 用乘法代替加法减少时间复杂度&#xff08;思想是离散化&#xff09; 2021-12-2 序列查询新解 分段处理 用乘法代替加法减少时间复杂度&am…

echarts绘制柱状图

<template><div><div>【大区数据信息】</div><div ref"target" class"w-full h-full" ></div></div> </template><script setup> import { ref, onMounted, watch} from "vue"; import *…