[英]What type of cast is appropriate here?
我有一個像這樣定義的名為BaseNode
抽象類模板
template<class T>
class BaseNode
{
public:
T* addChildNode(const char *name);
void deleteChildNode(const char *name);
void deleteAllChildNodes();
T* findFirstNode(const char *name);
T* getChildNode(const char *name);
T* getChildNode(unsigned int index);
void setName(const char *name);
void setTranformation(const glm::mat4 &transformation);
unsigned int getNumChildren() const { return _children.size(); }
const char *name() const { return _name.c_str(); }
T* parent() const { return _parent; }
const glm::mat4& transformation() const { return _transformation; }
const glm::mat4& toRootTransformation() const { return _toRoot; }
protected:
BaseNode(const char *nodeName, T *parent);
virtual ~BaseNode();
std::string _name;
glm::mat4 _transformation;
glm::mat4 _toRoot;
T *_parent;
std::vector<T*> _children;
};
該類的功能是,我可以創建自己的“節點類”類型,然后它們將繼承該類模板的所有場景圖方法。 (例如, class MyNode : public BaseNode<MyNode> {...};
該addChildNode(const char *name)
函數插入一個new T(name, this)
給孩子矢量,當this
應該是孩子的父母。 編譯器拋出強制類型轉換錯誤,並建議我為此使用某種強制類型轉換。 我目前正在使用dynamic_cast
,但這確實讓我感到困擾,因為我認為它沒有用。
我的問題是,在這種情況下使用reinterpret_cast(基本上就像C-cast ..?)是否安全,例如: _children.push_back(new T(name, reinterpret_cast<T*>(this)));
因為IMO dynamic_cast將永遠不會失敗。
這是一個奇怪的重復模板模式的例子,因此static_cast
在這里是慣用的。
在這種情況下,您可以通過多種方式避免進行投射。 最簡單的是將構造函數更改為:
BaseNode(const char* nodeName, T* parent, T* thisAsT);
並添加適當的字段:
//...
T* _parent;
T* _thisAsT;
因此,在addChildNode
您可以輕松訪問具有適當類型的this
指針:
_children.push_back(new T(name, _thisAsT));
當然,這需要您的派生類在其構造函數中為此參數提供有效的指針。
另一個,但是有點麻煩的是添加:
virtual T* buildFromName(const char* name) = 0;
然后在addChildNode
使用它:
_children.push_back(buildFromName(name));
但是,這需要派生類為自己的類型實現工廠方法,例如,這違反了SRP 。 另一方面,為每個派生類創建工廠類型似乎是一個過大的選擇。
第二個想法,具有與上述類似的屬性:
virtual T* getThis() = 0;
接着:
_children.push_back(new T(name, getThis()));
旁注:
-考慮使用std::string
而不是const char*
-聲明應寫為T* x
而不是T *x
(也可以用const char* x
代替const char *x
)-星號不是變量名稱的一部分,它是類型說明符的一部分,因此應啟用“類型方面”
static_cast是正確的。
dynamic_cast比您需要的慢得多。 reinterpret_cast錯誤。 您不知道派生對象的基類部分在與派生對象相同的位置開始。 如果需要,靜態強制轉換會調整地址。 reinterpret_cast沒有。
dynamic_cast和reinterpret_cast仍然不同。 如果基類和派生類的大小不同,則指向同一對象的基類指針和派生類指針可能具有不同的地址-如果存在虛擬表。
請參閱: 關於動態轉換以及基礎對象和派生對象的地址
如果沒有虛擬方法,則static_cast將執行->編譯時間轉換(執行速度更快)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.