C ++将子子类转换为基类

时间:2018-11-24 20:47:21

标签: c++ multiple-inheritance

具有以下类别:

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()返回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的废话值,因此任何建议或信息都将不胜感激!

3 个答案:

答案 0 :(得分:3)

我将忽略这种设计的众多问题,只是假设您有非常个很好的理由(即无法更改设计)想要做您想要的事情。如果您知道someOtherMethod()返回了指向void*对象的ChildChildClass,则可以先将static_cast的{​​{1}}指向void*,然后然后要么对ChildChildClass*进行显式上载,要么仅将BaseClass*用作ChildChildClass*,因为无论如何它都可以隐式转换(无需为此目的而进行上载自BaseClass*公开源自ChildChildClass以来调用该方法的过程):

BaseClass

但是,根据上面的代码,我被认为是您实际上并不知道ChildChildClass* initialPointer = static_cast<ChildChildClass*>(someOtherMethod()); BaseClass* basePointer = static_cast<BaseClass*>(initialPointer); 返回指向someOtherMethod()对象的指针。否则,为什么还要在转换为ChildChildClass之前检查它是否这样做?如果您不知道ChildChildClass*返回的void*所指向的对象的具体类型,则无法执行要在此处执行的强制转换(因为有一种知道的方法)实际应将其转换为什么)。一种解决方案是将someOtherMethod()更改为始终返回一个someOtherMethod()或至少肯定会始终指向一个BaseClass*对象的void*……

答案 1 :(得分:1)

您应使用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; 

答案 2 :(得分:0)

我建议使用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修改为返回BaseClass*

BaseClass* basePointer = someOtherMethod();

然后,其余代码不太可能成为问题。