我正在努力确认我已经在实践中工作的背后的理论。完整设置有点扭曲,因为功能在不同的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();
我有一些朦胧的记忆,有人告诉我,投入一个完全虚拟的课是一个特例 - 但我不记得为什么,或在网上找到任何关于它的东西。
请帮帮我 - 为什么我的代码有用?!
答案 0 :(得分:1)
这完全依赖于类布局,这是实现定义的,不能依赖它。特别是对于MSVC,类布局的一个很好的介绍是http://www.openrce.org/articles/full_view/23,值得知道你可以要求带有/d1reportSingleClassLayout
标志的类布局。
在您的情况下,由于第一个BaseClass
没有虚拟成员,因此它将被放置在DerivedClass
内的非指定位置。我猜DerivedClass
有一些虚拟成员,否则我希望BaseClass
位于DerivedClass
的开头且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调用。