我正在尝试确认我已经在实践中工作的背后的理论。完整的设置有些扭曲,因为功能是在不同的dll之间分配的,但是我将尝试描述这种情况:

class __declspec( dllexport ) BaseClass
/** This class' definition is available to everything,
 *  via .h file, .dll and .lib. */
{
    protected:
        std::string name;

    public:
        std::string GetName();
        /** This is implemented in BaseClass, and just returns this->name. */
}




class DerivedClass: public BaseClass
/** This class is created within the executable, but is not 'visible' to other
 *  dlls - either through .h files, .lib, or anything else. */
{
    public:
        DerivedClass();
        /** This sets this->name based on its own propertied. */
}


此转换有效,但需要完全访问DerivedClass的定义:

void* pointer;
DerivedClass* derived_pointer = reinterpret_class<DerivedClass*>(pointer);
BaseClass* base_pointer = dynamic_cast<BaseClass*>(derived_pointer);
base_pointer->GetName();


但是,以下操作无效:

void* pointer;
BaseClass* base_pointer = reinterpret_class<BaseClass*>(pointer);
base_pointer->GetName();


为了解决这个问题,我实现了一个接口:

class __declspec( dllexport ) IBaseClass
/** Fully virtual 'interface' class, in same file as BaseClass. */
{
    public:
        virtual std::string GetName() = 0;
}

class __declspec( dllexport ) BaseClass: public IBaseClass
/** This class' definition is available to
 *  everything, via .h file, .dll and .lib. */
{
    protected:
        std::string name;

    public:
        std::string GetName();
        /** This is implemented in BaseClass, and just returns this->name. */
}




class DerivedClass: public BaseClass
/** This class is created within the executable, but is not 'visible'
 *  to other dlls - either through .h files, .lib, or anything else. */
{
    public:
        DerivedClass();
        /** This sets this->name based on its own propertied. */
}


现在,以下代码可以正常工作:

void* pointer;
IBaseClass* ibase_pointer = reinterpret_class<IBaseClass*>(pointer);
ibase_pointer->GetName();


我对有人告诉我说,强制转换为完全虚拟的类是一种特例-但我不记得为什么,或者在网上找不到任何有关它的信息。

请帮助我-为什么我的代码有效?

最佳答案

这完全取决于类布局,该类布局是实现定义的,因此不能依赖。专门针对MSVC,http://www.openrce.org/articles/full_view/23是类布局的一个很好的介绍,值得一提的是,您可以使用/d1reportSingleClassLayout标志请求类布局。

在您的情况下,由于第一个BaseClass没有虚拟成员,因此它将被放置在DerivedClass内的未指定位置。我猜想DerivedClass有一些虚拟成员,否则我希望BaseClassDerivedClass的开头并且reinterpret_cast可以工作。如果它具有虚拟成员,您将拥有:

+--------------------+
|DerivedClass vtable |
|BaseClass::name     |
|DerivedClass members|


通过添加接口IBaseClass,没有任何变化。 DerivedClass的布局仍为:

+--------------------+
|DerivedClass vtable |
|BaseClass::name     |
|DerivedClass members|


但是,DerivedClass vtable以IBaseClass vtable开头:

+---------------------+
|IBaseClass::GetName  |
|DerivedClass virtuals|


因此通过DerivedClass vtable调用即可。

关于c++ - 上流到父类(super class)或接口(interface)?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11455134/

10-10 17:08