【发布时间】:2014-01-27 04:16:06
【问题描述】:
我有一个控制器函数来处理许多对象,这些对象的特定类都派生自纯虚拟类。
class Abstract {
public:
virtual bool ReadyForWork() = 0;
virtual void DoWork() = 0;
};
然后我有以下内容:
class Specific : public virtual Abstract {
public:
bool ReadyForWork();
void DoWork();
};
程序创建一个 Specific 实例并将其分配给链中的一个 void 指针。
vChain->Append(new Specific());
到目前为止,一切都很好。当控制器函数启动并尝试访问具体的 Abstract 虚拟函数的实现时,虽然...... eww。
Specific 对象就在那里,我可以通过将 vChain 的内部 void* 转换为 Specific* 来访问它的内容,并且一切都会检查出来,所以内存不足不是问题。但是当我将 void* 转换为 Abstract* 时,编译器会丢失对 Specific 实现的引用,将函数地址更改为与以前完全不同的地址——即使指向对象本身的指针是正确的。尝试
// ...
Abstract *vWorkObj = (Abstract*)vChain->GetObj();
if (vWorkObj->ReadyForWork()) {
// ...
在我的脸上产生以下结果:
Unhandled exception at 0x00000054 in Proj.exe:
0xC0000005: Access violation executing location 0x00000054.
但如果我这样做
// ...
Abstract *vWorkObj = (Specific*)vChain->GetObj();
if (vWorkObj->ReadyForWork()) {
// ...
它运行顺利。不幸的是,这对我没有多大帮助,因为将会有多个类继承自 Abstract。
我在一个概念验证项目中尝试过类似的东西,并且运行顺利:
// ...
bool ReadyForWork(Abstract *pObjPtr) {
// ...
// ...
Specific *vObj = new Specific();
if (ReadyForWork(vObj)) {
// ...
显然编译器不喜欢在运行时解析继承类。 有没有办法访问抽象类的继承者而不显式告诉编译器它是哪个继承者?
我怀疑与 void* 之间的转换可能是导致编译器迷失方向的原因,但如果链尽可能保持通用性,它将节省一些麻烦。
我正在为 Windows 桌面使用 VS2013 Express。感谢您的宝贵时间。
【问题讨论】:
-
尝试不使用虚拟继承。 vChain->Append() 的参数类型是什么?
-
@EJP:呵呵!去掉虚拟继承修复了它。谢谢。 Append() 恰好采用 void* 参数。
标签: c++ pointers casting abstract derived