什么类型的cast在这里是合适的
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> {...};
当this
应该是子向量的父向量时,addChildNode(const char *name)
函数将new T(name, 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进行编译时强制转换(执行速度更快)。
- ArduinoJson 6.15.2:JsonObject没有命名类型
- 防止主数据类型C++的隐式转换
- 大量序列中核苷酸类型的快速计数
- 如何从C++中的依赖类型中获得它所依赖的类型
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如何获取std::result_of函数的返回类型
- 从父命名空间重载类型
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 访问者访问变体并返回不同类型时出错
- 如何理解C++标准N3337中的expr.const.cast子句8
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 模板元程序查找相似的连续类型名称
- 错误:"cast"未命名类型void setCastDescription(std::string
- 什么类型的Cast从父母到孩子
- 什么类型的cast在这里是合适的