【发布时间】:2015-09-09 10:10:36
【问题描述】:
我有一个名为 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最接近 C-cast。 -
@TartanLlama 看看 MyNode 示例。
-
不要重新解释从父指针到子指针的转换,反之亦然。这是 UB,如果您有多重继承,它肯定会因某些基类而失败。请改用 static_cast。实际上更喜欢 dynamic_cast,除非您知道它会在您的程序中导致显着的性能损失。仅使用 reinterpret_cast 将您的指针投射到(可能是 cv-qualified)
void*或char*并返回。 -
@n.m 仅当怀疑对象的运行时类型是否与 static_cast 兼容时,我才会使用 dynamic_cast。 C++ 程序几乎在任何地方都存在固有的程序员错误。编码效率低下(即使效率不重要)以关闭一个微小的程序员错误来源,是愚蠢的。
-
@JSF 愚蠢的是一个生产系统会遇到 UB、失控并破坏客户数据,而不是在一个复杂的、未经正式验证的系统中检测和报告逻辑错误。