簡體   English   中英

C ++轉換,用於C風格的向下轉換

[英]C++ casting for C-style downcasting

當使用使用C樣式繼承(利用C結構的標准布局)的C API(例如GLib)時 ,我們通常使用C樣式強制轉換進行向下轉換:

struct base_object
{
    int x;
    int y;
    int z;
};

struct derived_object
{
    base_object base;
    int foo;
    int bar;
};

void func(base_object* b)
{
    derived_object* d = (derived_object*) b; /* Downcast */
}


但是,如果我們正在編寫使用像這樣的C-API的新C ++代碼,是否應該繼續使用C樣式的強制轉換,還是應該選擇C ++強制轉換? 如果是后者,我們應該使用哪種類型的C ++強制轉換來模擬C向下轉換?

起初,我認為reinterpret_cast將是合適的:

derived_object* d = reinterpret_cast<derived_object*>(b);

但是,我總是對reinterpret_cast保持警惕,因為C ++標准幾乎不會保證會發生什么。 使用static_castvoid*可能更安全:

derived_object* d = static_cast<derived_object*>(static_cast<void*>(b))

當然,這確實很麻煩,讓我認為在這種情況下最好使用C樣式的強制轉換。

那么,這里的最佳實踐是什么?

像這樣使用C-API的新C ++代碼

不要以C風格編寫新的C ++代碼,它不會利用C ++語言功能,而且還會迫使包裝器用戶使用相同的“ C”風格。 而是創建一個適當的C ++類,該類包裝C API接口詳細信息並將其隱藏在C ++類后面。

我們應該繼續使用C樣式的強制類型轉換嗎

沒有

還是我們更喜歡C ++強制轉換

是的,但是只有在必須的時候。

使用C ++繼承和虛擬訪問器功能(可能)。 請說明您打算如何在func中使用派生對象,這可能為您提供更好的答案。

如果func希望使用派生對象的方法,則它應該接收派生對象。 如果它希望使用base_object的方法,但是由於指針指向了一個Applied_object,則方法有所改變,那么虛函數就是實現此目的的C ++方法。

另外,您想傳遞對func的引用,而不是指針。

dynamic_cast,需要滿足某些條件:

http://www.cplusplus.com/doc/tutorial/typecasting/

如果您只是將struct ptrs轉換為struct ptrs,並且知道自己想要什么,那么static_cast或reinterpret_cast可能是最好的?

但是,如果您真的對編寫C ++代碼感興趣,則強制轉換應該是您的最后也是最后的手段,因為有更好的模式。 我會考慮轉換的兩種常見情況是:

  • 您正在與某種事件傳遞機制進行接口,該機制將通用基類傳遞給事件處理程序。

  • 您有一個對象容器。 容器要求它包含同質類型(即,每個元素都包含相同的“事物”),但是您想在容器中存儲不同的類型。

但是,我總是對reinterpret_cast保持警惕,因為C ++標准幾乎不會保證會發生什么。

C ++樣式強制轉換與C樣式強制轉換一樣安全,因為C樣式強制轉換是根據C ++樣式強制轉換定義的。

5.4.4執行的轉換

— const_cast(5.2.11),

— static_cast(5.2.9),

—后面是const_cast的static_cast,

—一個reinterpret_cast(5.2.10),或

—一個reinterpret_cast,然后是const_cast,

可以使用顯式類型轉換的強制轉換符號執行。

[...]

如果可以用以上列出的一種以上的方法來解釋轉換,則使用列表中第一個出現的解釋,即使該解釋導致的轉換格式不正確。

可悲的答案是,您不能避免像編寫代碼那樣強制轉換代碼,因為編譯器對類之間的關系了解甚少。 您可能需要某種方式進行重構(廣播或類或使用它們的代碼)。

底線是:

如果可以,請使用適當的繼承。

如果不能,請使用reinterpret_cast。

如果您在C ++規范中查看C樣式轉換的規范,您會發現轉換符號是根據其他類型轉換運算符( dynamic_caststatic_caststatic_castreinterpret_castconst_cast )定義的,在這種情況下, reinterpret_cast使用reinterpret_cast

另外,與您鏈接到的答案相比, reinterpret_cast提供的保證更多。 您關心的是:

第9.2 / 20節:指向標准布局結構對象的指針(使用reinterpret_cast進行了適當轉換)指向其初始成員(或者,如果該成員是位字段,則指向其駐留的單元),反之亦然。

如果要使用強制轉換表示法,我認為最好顯式使用C ++類型轉換運算符。 但是,與其亂扔整個代碼,不如應該為每次轉換編寫一個函數(使用reinterpret_cast實現),然后使用它。

derived_object *downcast_to_derived(base_object *b) {
    return reinterpret_cast<derived_object*>(b);
}

我認為dynamic_cast正是您想要的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM