[英]Right cast for a void* pointer
我正在嘗試使用一個可以指向任何value
字段實現C ++類(有點像boost :: any)。 目前,我正在執行以下操作:
class MyClass {
void* value;
template<typename T>
Myclass(const &T v) {
value = (void*)(new T(v));
}
};
現在的問題是實現一個getValue()操作,該操作創建具有正確類型的內部值的副本:
template<typename T>
T getValue() {
return *value;
}
在這里它不能工作,因為我試圖取消引用void *指針。 我想知道應該使用哪種類型的轉換(static_cast?dynamic_cast?other ...),以便將* value正確轉換為T對象,並且如果value最初不是這種類型,則會引發異常?
謝謝
您不能取消引用void*
,這根本沒有意義。 為什么不使類本身具有泛型? 然后您可以擁有:
template<typename T>
class MyClass {
T* value;
MyClass(const T& v) {
value = new T(v);
}
T getValue() {
return *value;
}
};
確保創建一個析構函數,該析構函數可以分配value
並遵循“三法則” 。 您也可以創建一個getValue
版本,該版本返回const T&
(指向T
const
引用)以避免不必要的復制。
我應該使用哪種轉換(static_cast?dynamic_cast?other ...),以便將* value正確轉換為T對象
如果必須執行此轉換,則應使用static_cast
,通常將其用於(除其他事項外)撤消任何標准轉換。 從任何對象指針類型到void*
都有標准轉換,您的getter會將其反轉,因此請使用為此設計的強制轉換:
return *static_cast<T*>(value);
您還應該從構造函數中刪除C樣式static_cast
,或者也將其替換為static_cast
。
reinterpret_cast
也可以,但是“過度殺傷”。 通常,在執行所需轉換的同時,應使用盡可能嚴格的轉換。
如果value最初不是此類型,則拋出異常
您真不走運-一旦將指針轉換為void*
,C ++通常就無法確定對象的原始類型是什么。 您的代碼依賴於調用方以正確的類型調用getValue
。 例如,考慮一下如果原始類型是char
,會發生什么情況-在C ++中只有一個字節,那么就沒有為任何類型信息留出空間,這將允許編譯器檢查getValue
中的getValue
。
dynamic_cast
在某些有限的情況下會檢查類型,但是由於您的模板是完全通用的,因此這些有限的情況可能不適用。
如果您不喜歡這樣做,則除了對象指針外,還可以更改類以存儲指向type_info
對象的指針(使用typeid
運算符)。 參見標准標題<typeinfo>
。 然后,您可以比較type_info
對象類型T
的構造,與type_info
的對象類型T
中getValue
,並拋出,如果他們不匹配。
就像您說的那樣,您的類打算有點像boost::any
,而getValue
就像any_cast
。 您可以查閱該類的源代碼和文檔,以了解完成所需的技巧。 如果有一種簡單的方法,那么boost::any
將是一個簡單的類!
你不能 C ++不會(至少不是直接)提供這種機制,不是針對void*
。 void*
沒有任何信息表明計算機將需要確定它是什么,並且嘗試“檢查”它是否是有效的(隨便播報)是不可能的,因為沒有針對它的特定標志。
雖然有選擇。 首先是使用某種類似於Java的Object的通用基類,並從中派生所有其他類。 現在, dynamic_cast
將按照您想要的方式工作(如果對象不是將其強制轉換為的類的有效對象,則返回NULL
)。
另一個是簡單地跟蹤您自己屬於哪種類型的對象。 這意味着用另一個值擴展void*
,它告訴您需要將其強制轉換為什么。
但是,實際上,這些東西都不是我的好主意。 我認為您的設計中幾乎有其他方面應該更改而不是使用這些方面。 使用模板,如@EdS。 建議,例如,這是一個非常好的選擇。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.