C++ Cast sub-sub class 到 base
C++ Cast sub-sub class to base
下面类:
enum class OBJECT_TYPE {TYPE_1, TYPE_2, TYPE_3};
class BaseClass {
public:
BaseClass();
virtual ~BaseClass();
OBJECT_TYPE getObjectType() { return m_objectType; }
protected:
OBJECT_TYPE m_objectType;
}
class ChildClass : public BaseClass {
public:
ChildClass();
virtual ~ChildClass();
virtual void init() = 0;
protected:
// some other variables
}
class ChildChildClass : public ChildClass {
public:
ChildChildClass ();
~ChildChildClass ();
void init() override { m_objectType = OBJECT_TYPE::TYPE_3 }
private:
// some other variables
}
在代码库的单独部分,我如何将 void*
转换为 ChildChildClass
实例再转换为 BaseClass*
以便我可以调用 getObjectType()
确定它指向哪种类型的对象。我目前正在这样做:
(someOtherMethod()
returns一个void*
到一个ChildChildClass
)
void* initialPointer = someOtherMethod();
BaseClass* basePointer = static_cast<BaseClass>(initialPointer);
if (basePointer->getObjectType() == OBJECT_TYPE::TYPE_3) {
ChildChildClass* childChildPointer = static_cast<ChildChildClass*>(basePointer);
}
我想我在使用继承时可能会误解转换指针,因为我得到的返回值毫无意义 objectType
所以任何建议或信息将不胜感激!
您应该使用 reinterpret_cast<>
从 void*
投射:
BaseClass* basePointer = reinterpret_cast<BaseClass*>(initialPointer);
但要格外小心!如果 initialPointer
不会指向正确类型的对象,这就是 UB!
补充推荐:
对于向下转换,更安全的方法是使用 dynamic_cast<>
:
ChildChildClass* childChildPointer = dynamic_cast<ChildChildClass*>(basePointer);
if (! childChildPointer)
cout << "Something wrong happened !" <<endl;
我建议使用 dynamic_cast
。
// This is risky but I assume you know what you are doing.
// BTW, you are using static_cast<BaseClass>. That is not correct.
BaseClass* basePointer = static_cast<BaseClass*>(initialPointer);
// Now use dynamic_cast.
ChildChildClass* childChildPointer = dynamic_cast<ChildChildClass*>(basePointer);
if ( childChildPointer != nullptr)
{
// Use childChildPointer.
}
else
{
// Do something different.
}
如果someOtherMethod
可以修改成return一个BaseClass*
就更好了。
BaseClass* basePointer = someOtherMethod();
那么,其余代码不太可能成为问题。
我将忽略此类设计的众多问题,并假设您有非常充分的理由(即无法更改设计)想要做什么你要求的。如果你知道 someOtherMethod()
return 是一个指向 ChildChildClass
对象的 void*
,那么你可以先 static_cast
那个 void*
指向一个 ChildChildClass*
然后要么执行一个显式向上转换为 BaseClass*
要么只使用那个 ChildChildClass*
作为一个 BaseClass*
因为它无论如何都可以隐式转换(应该不需要执行向上转换只是为了调用方法,因为 ChildChildClass
公开派生自 BaseClass
):
ChildChildClass* initialPointer = static_cast<ChildChildClass*>(someOtherMethod());
BaseClass* basePointer = static_cast<BaseClass*>(initialPointer);
但是,根据您上面的代码,我相信您实际上并不知道 someOtherMethod()
return 是指向 ChildChildClass
对象的指针。否则,为什么在转换为 ChildChildClass*
之前必须检查它是否正确?如果您不知道 void*
returned by someOtherMethod()
指向的对象的具体类型,那么就无法在此处执行您想执行的转换(因为那里是了解实际应将什么转换为什么的方法)。一种解决方案是将 someOtherMethod()
更改为始终 return 一个 BaseClass*
或至少一个 void*
,你肯定知道它总是指向一个 BaseClass
对象......
下面类:
enum class OBJECT_TYPE {TYPE_1, TYPE_2, TYPE_3};
class BaseClass {
public:
BaseClass();
virtual ~BaseClass();
OBJECT_TYPE getObjectType() { return m_objectType; }
protected:
OBJECT_TYPE m_objectType;
}
class ChildClass : public BaseClass {
public:
ChildClass();
virtual ~ChildClass();
virtual void init() = 0;
protected:
// some other variables
}
class ChildChildClass : public ChildClass {
public:
ChildChildClass ();
~ChildChildClass ();
void init() override { m_objectType = OBJECT_TYPE::TYPE_3 }
private:
// some other variables
}
在代码库的单独部分,我如何将 void*
转换为 ChildChildClass
实例再转换为 BaseClass*
以便我可以调用 getObjectType()
确定它指向哪种类型的对象。我目前正在这样做:
(someOtherMethod()
returns一个void*
到一个ChildChildClass
)
void* initialPointer = someOtherMethod();
BaseClass* basePointer = static_cast<BaseClass>(initialPointer);
if (basePointer->getObjectType() == OBJECT_TYPE::TYPE_3) {
ChildChildClass* childChildPointer = static_cast<ChildChildClass*>(basePointer);
}
我想我在使用继承时可能会误解转换指针,因为我得到的返回值毫无意义 objectType
所以任何建议或信息将不胜感激!
您应该使用 reinterpret_cast<>
从 void*
投射:
BaseClass* basePointer = reinterpret_cast<BaseClass*>(initialPointer);
但要格外小心!如果 initialPointer
不会指向正确类型的对象,这就是 UB!
补充推荐:
对于向下转换,更安全的方法是使用 dynamic_cast<>
:
ChildChildClass* childChildPointer = dynamic_cast<ChildChildClass*>(basePointer);
if (! childChildPointer)
cout << "Something wrong happened !" <<endl;
我建议使用 dynamic_cast
。
// This is risky but I assume you know what you are doing.
// BTW, you are using static_cast<BaseClass>. That is not correct.
BaseClass* basePointer = static_cast<BaseClass*>(initialPointer);
// Now use dynamic_cast.
ChildChildClass* childChildPointer = dynamic_cast<ChildChildClass*>(basePointer);
if ( childChildPointer != nullptr)
{
// Use childChildPointer.
}
else
{
// Do something different.
}
如果someOtherMethod
可以修改成return一个BaseClass*
就更好了。
BaseClass* basePointer = someOtherMethod();
那么,其余代码不太可能成为问题。
我将忽略此类设计的众多问题,并假设您有非常充分的理由(即无法更改设计)想要做什么你要求的。如果你知道 someOtherMethod()
return 是一个指向 ChildChildClass
对象的 void*
,那么你可以先 static_cast
那个 void*
指向一个 ChildChildClass*
然后要么执行一个显式向上转换为 BaseClass*
要么只使用那个 ChildChildClass*
作为一个 BaseClass*
因为它无论如何都可以隐式转换(应该不需要执行向上转换只是为了调用方法,因为 ChildChildClass
公开派生自 BaseClass
):
ChildChildClass* initialPointer = static_cast<ChildChildClass*>(someOtherMethod());
BaseClass* basePointer = static_cast<BaseClass*>(initialPointer);
但是,根据您上面的代码,我相信您实际上并不知道 someOtherMethod()
return 是指向 ChildChildClass
对象的指针。否则,为什么在转换为 ChildChildClass*
之前必须检查它是否正确?如果您不知道 void*
returned by someOtherMethod()
指向的对象的具体类型,那么就无法在此处执行您想执行的转换(因为那里是了解实际应将什么转换为什么的方法)。一种解决方案是将 someOtherMethod()
更改为始终 return 一个 BaseClass*
或至少一个 void*
,你肯定知道它总是指向一个 BaseClass
对象......