我尝试了两种不同的方法从基指针获取指向派生类的指针。一种方法是:
struct BaseClass {
protected:
int offset_of_derived;
public:
template <typename T>
T* getAs() { return (T*)((char*)this + offset_of_derived); }
protected:
char* getBasePtr() { return (char*)this; }
};
template <typename T>
struct DerivedClass : BaseClass
{
DerivedClass() : BaseClass() { this->offset_of_derived = (char*)this - BaseClass::getBasePtr(); }
};
而且没有必要,std::launder
因为我所做的只是从 char 进行转换并返回,以及从 Base – Derived 进行转换,对吗?
6
最佳答案
1
“从基类型指针获取派生类的最佳方法是什么?”
您似乎试图手动实现该语言已经提供的功能。
您可以使用两种相关的语言结构:
-
最强大的(但由于运行时检查,效率稍低)是。它:
沿着继承层次结构安全地向上、向下和横向转换对类的指针和引用。
如果你不确定层次结构中的对象类型,只需使用
dynamic_cast
。如果你请求的转换无效,它将返回一个空指针,因此你可以随时检查自己。 -
如果您确定该对象实际上是派生对象,则可以使用
static_cast
(不会引起运行时检查):向下转型也可以用 static_cast 来执行,这样可以避免运行时检查的成本,但只有当程序可以保证(通过其他逻辑)表达式指向的对象肯定是 Derived 时才是安全的。
请注意,如果您使用的
static_cast
对象不是预期的派生对象,则行为未定义。
用法示例dynamic_cast
:
BaseClass * p1 = get_object_pointer(); // some function that returns a pointer to an object in the hirarchy
DerivedClass * p2 = dynamic_cast<DerivedClass*>(p1); // p2 will be a null pointer if conversion is invalid
用法示例static_cast
:
BaseClass * p1 = new DerivedClass;
DerivedClass * p2 = static_cast<DerivedClass*>(p1); // OK - we know p1 points to DerivedClass
或者如果您想将其作为方法模板,BaseClass
那么按照您可以添加:
template <typename T>
T* getAs() { return dynamic_cast<T*>( this ); } // or use `static_cast` under the limitations explained above
|
static_cast
将完成该工作,否则使用dynamic_cast
。鉴于上述情况,我想我不明白这个问题。–
–
char*
)时,您都应该将其视为您可能做错了什么的迹象。您要解决的实际和潜在问题是什么?只是简单的向下转换?那么为什么不能使用 @RichardCritten 提到的 C++ 强制转换运算符?–
–
derived_cast()
函数模板,该模板static_cast()
在可能的情况下应用,dynamic_cast()
否则应用。这在您知道基类指针指向某个派生类的实例(或为nullptr
)的情况下非常方便。dynamic_cast
如果涉及虚拟继承,则需要。–
|