向上转换到超类或接口



我正在努力证实我在实践中已经做过的一些事情背后的理论。完整的设置有些扭曲,因为功能在不同的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|

因此通过CCD_ 10vtable进行调用是可行的。

相关内容

  • 没有找到相关文章

最新更新