Open CASCADE Foundation Classes – Basics
Open CASCADE Foundation Classes – Basics
Open CASCADE 基礎庫之基本功能
本章主要介紹Open CASCADE的基本功能,如記憶體管理(memory management)、手柄程式設計(programming with handles)、基本型別(primitive types)、異常處理(exception handling)、泛型程式設計(genericity by downcasting)、Plug-in的建立等……
一、資料型別 Data Types
1.1 基本型別 Primitive Types
基本型別是由語言定義的且他們是由值控制的。有些基本型別從類Storable
l Boolean: 用來表示邏輯資料。只有兩種狀態:Standard_True和Standard_False;
l Character: 用來表示任意ASCII字元;
l ExtCharacter: 用來表示字元的擴充套件;
l Integer: 用來表示整數;
l Real: 用來表示實數;
l ShortReal: 用來表示實數的另一種選擇,精度要低;
也有非儲存型別,如:
l CString:
l ExtString:
l Address:
下表所示為Open CASCADE中基本型別與C++中基本型別對應表:
C++ Types | Open CASCADE Types |
int | Standard_Integer |
double | Standard_Real |
float | Standard_ShortReal |
unsigned int | Standard_Boolean Standard_False = 0; Standard_True = 1; |
char | Standard_Character |
short | Standard_ExtCharacter |
char* | Standard |
void* | Standard_Address |
short* | Standard_ExtString |
具體請參考《Open CASCADE Foundation Classes User's Guide》;
1.2 由值控制的型別
由值控制的變數型別分為三類:
l 基本型別;
l 列舉型別;
l 不是由類Standard_Persistent直接或間接派生的類;
由值控制的變數比由手柄控制的變數更直接,更快,就是不能儲存到檔案。
1.3 由引用控制的型別
由手柄控制的變數分為兩類:
l 由類Persistent派生的類,這種類可以儲存到檔案;
l 由類Transient派生的類;
1.4 屬性的結論
二、手柄程式設計 Programming with Handles
2.1 手柄定義 Handle Definition
手柄與C++的指標(pointer)類似。幾個手柄可以引用同一個物件,同樣地,一個手柄也可以引用了幾個物件,但是一次只能是一個物件。為了訪問引用的物件,必須先解除引用(de-referenced),就像使用C++的指標一樣。臨時變數和持久變數既可以是由值控制的也可以是由手柄控制的。引用非永續性物件的手柄稱為不可儲存手柄。因此,永續性物件不能包含不可儲存手柄。
類的組織:使用手柄的類的物件可以是持久的也可是臨時的。從類Standard_Transient繼承的類的例項是臨時的,而從類Standard_Persistent繼承的類的例項是持久的。本章只討論臨時類及其相關的手柄。持久類及其相關的手柄的組織與此類似。
類Standard_Transient是Open CASCADE中由手柄控制的類層次結構中的基類。它有引用計數部分,所有的子類都繼承此部分。當使用Handle()類時,就可知引手柄引用例項的數量。
直接或間接由類Transient派生的類,CDL extractor將建立類的相應的手柄Handle(),類名是相同的,只是在類名前加上了“Handle_*”。Open CASCADE提供前處理器的巨集定義Handle(),用來產生相應類的帶手柄的類。
使用手柄:在對臨時物件執行任何操作之前,你必須宣告手柄。如:若點(Point)和線(Line)是從包Geom中定義的兩個臨時物件,程式碼如下:
宣告手柄建立了一個未指向任何物件的空手柄。手柄可以通過其方法IsNull()來驗證。使用手柄無效,可使用方法Nullify()。
只要型別相容,既可以從建立新的物件或通過賦值來初始化手柄。手柄僅用於共享的物件。對於所有的本地操作,建議使用由值控制的類。
2.2 型別管理 Type Management
Open CASCADE提供一種描述資料型別層次的通用方式,並且可以執行時檢查物件型別,與C++的RTTI類似。對於從類Standard_Transient繼承的每個類,CDL extractor從類Standard_Type建立程式碼。由類Standard_Transient派生的類的虛擬函式DynamicType()返回一個例項。通過虛擬函式IsKind()來檢查給定的物件是不是指定的型別。
2.3 使用手柄建立物件 Using Handles to Create Objects
建立由手柄控制的物件,宣告手柄並使用標準C++的new操作符,緊隨其後呼叫建構函式。
與指標不同的是,手柄不需要delete。因為當手柄引用的物件為零時,物件將會被自動釋放。
2.4 方法呼叫 Invoking Methods
當你使用手柄的時候,就跟使用C++的指標一樣。呼叫手柄引用物件的方法使用操作符->。檢查或修改手柄的狀態,通過操作符點.來實現。下例所示為訪問一個點物件的座標:
下例所示為如何檢查笛卡爾座標點的型別:
當呼叫一個空Null手柄時,NullObject異常將會產生。
呼叫類方法:類方法就是C++類中的靜態函式。即用類名加上“::”和方法名來呼叫。
2.5 手柄釋放 Handle De-allocation
在刪除一個物件之前,必須其沒有被引用。為了減少管理物件生命週期的程式設計工作量,Open CASCADE中物件的刪除函式是由手柄控制類的引用計數(reference counter)來確保。手柄就是用來管理引用計數,當物件不再引用時將會呼叫delete將其刪除。當是Standard_Transient的子類時,通常不需要直接使用delete操作符。當對相同的物件使用new時,引用計數將會增加。當手柄被銷燬、置為空或重新賦值,引用計數將會減少。當引用計數為0時物件將會自動呼叫delete操作符。記憶體分配的原理如下所示:
Cycles
本段內容不清楚,具體內容請參考原文。
2.6 不使用CDL建立類 Creating Transient Classes without CDL
儘管可用CDL extractor生成手柄類及其相關C++程式碼,然而也可不用CDL管理手柄。為此,在檔案Standard_DefineHandle.hxx中提供了幾個巨集定義:
DECLARE_STANDARD_HANDLE(class_name, ancestor_name) 這個巨集定義了以class_name為類名並繼承類ancestor_name的手柄類。這個巨集必須放在標頭檔案中,且基類必須是可用的。
IMPLEMENT_STANDARD_HANDLE(class_name, ancestor_name) 這個巨集實現了轉換方法DownCast(),應該在C++檔案中使用。
DEFINE_STANDARD_RTTI(class_name) 這個巨集宣告方法需要RTTI支援,應該在類的public中使用。
IMPLEMENT_STANDARD_RTTIEXT(class_name, ancestor_name) 實現上面的方法。
注:在使用這些巨集的時候,必須確保引數的正確性,特別是父類的名字。否則定義將會不正確,且編譯也不會報錯。
三、記憶體管理 Memory Management in Open CASCADE
在幾何建模的過程中,程式建立和刪除相當數量的C++物件在動態記憶體中,也就是堆中(heap)。在這種情況下,標準函式管理記憶體的效能可能不足夠。所以,Open CASCADE在標準包中實現了記憶體的管理。
3.1 用法 Usage
使用Open CASCADE記憶體管理只需要在C中使用malloc()的地方使用Standard::Allocate();在使用free()的地方使用Standard::Free();在使用realloc()的地方使用Standard::Reallocate()。
在C++中,類的操作符new()和delete()已經定義了在申請記憶體時使用Standard::Allocate()並在釋放時使用Standard::Free()。所以,類所有的物件的記憶體都將由Open CASCADE的記憶體管理器來管理。
CDL extractor為所有的類定義了new()和delete()。所以,所有的Open CASCADE的類(小部分除外)都使用Open CASCADE的記憶體管理器。
由於操作符new()和delete()被繼承,所以,所有從Open CASCADE派生的類,所有從Standard_Transient類派生的類都是由記憶體管理器管理。
注:若過載了部分從Standard_Transient類派生類的new()和delete(),儘管不推薦這樣做,方法Delete()必須重定義,以便對這樣的指標使用delete操作。這將確保合適的delete()函式將會被呼叫,即使是由手柄控制的物件。
3.2 配置記憶體管理器 Configuring Memory Manager
Open CASCADE記憶體管理器可以被配置以便對不同的記憶體區域使用不同的優化技術,或者根本不使用任何優化而直接使用C的malloc()和free()函式。配置方法為修改環境變數的值:
l MMGT_OPT:
l MMGT_CLEAR:
l MMGT_CELLSIZE:
l MMGT_NBPAGES:
l MMGT_THRESHOLD:
l MMGT_REENTRANT:
3.3 實現細節 Implementation details
本段內容請參考原文。
四、異常處理 Exception Handling
異常處理提供了一種從指定點轉換到其他點的一種方法。一個方法可能會產生一個異常,將程式從正常執行處轉換到捕捉異常處。Open CASCADE提供了異常類的層次,其基類是包Standard中的Standard_Failure。CDL extractor使用標準介面生成異常類。
Open CASCADE也提供將系統訊號的轉換成異常的支援,如數除0這樣所有的情況都可以用安全、統一的方法來處理了。但是為了支援不同的平臺,也使用了一些特殊的方法。
如下內容為在Open CASCADE中使用異常處理的推薦方法。
4.1 產生異常 Raising an Exception
類C++的語法:產生適當的異常將需要呼叫指定型別的Raise()方法。
產生了一個DomainError型別的異常並可附上相關資訊“Cannot cope with this condition”,資訊字串是可選的。這個異常可以被捕捉DomainError型別的Handler捕捉到:
正常使用異常處理:異常不能被當作程式設計技巧來替代“goto”,但可作為防止方法被誤用的一種方法。
五、Plug-In管理
本段內容請參考原文。
六、結論
本章內容介紹了一些C++程式設計的知識及Open CASCADE對C++的包裝。其中,手柄程式設計是C++中常見的方法,這種引用計數的方式使記憶體的管理更方便。
Pudongxin Shanghai China
2012-8-23