让我们来看看下面的代码:
class CBase
{
public:
virtual vfunc() { cout << "CBase::vfunc()" << endl; }
};
class CChild: public CBase
{
public:
vfunc() { cout << "CChild::vfunc()" << endl; }
};
int main()
{
CBase *pBase = new CBase;
((CChild*)pBase)->vfunc(); // !!! important
delete pBase;
return 0;
}
输出是:
CBase::vfunc()
但我想看看:CChild :: vfunc()
显式((CChild *)PBASE)强制转换成键入 “CChild *”。 那么,为什么叫得出vfunc()我需要更换为 “重要” 的字符串:((CChild *)PBASE) - > CChild :: vfunc();
这不是它的工作原理 - 这就是:
CBase *pBase = new CChild;
pBase->vfunc();
virtual
函数调用的指针和引用动态解析(除非你明确地调用该方法,像你这样)。 这意味着它并不重要,你分不清什么编译器的指针,它会寻找在vftable的方法。 其中,在你的情况,是vftable
的CBase
。
你不能。 *pBase
是类型的对象CBase
。 你不能把它当作好像它是一个CChild
,因为它不是一个CChild
对象。
通过投所获得的指针使用CChild*
使你的程序出现不确定的行为。
其他答案作出重要点-补充:如果你实际上可能有要处理CChild
(例如,它是作为参数传递的引用),那么你可以使用dynamic_cast
向下转型。 然而,在高度依赖dynamic_cast
通常表明你的设计出了问题。
上投细节可以在这里找到: http://msdn.microsoft.com/en-us/library/cby9kycs(v=vs.80).aspx
所以这个过程将需要铸造CBase
参数CChild
通过dynamic_cast
,如果引用是CChild
和dynamic_cast
成功,那么你可以确保你正在处理一个CChild
,然后就可以放心地使用它作为一个CChild
。
这里的问题似乎很简单。 CBase类不能神奇地升级到CChild! 让我重写你的榜样,并添加一些评论。 这应该是不言而喻的......
#include <iostream>
class CBase {
public:
virtual void vfunc() { std::cout << "CBase::vfunc()" << std::endl; }
virtual ~CBase(){} // Virtual destructor... extremely important! I'll let you figure out why as an excercise
};
class CChild: public CBase {
public:
void vfunc() { std::cout << "CChild::vfunc()" << std::endl; }
~CChild(){} // Is this destructor called? When? Try adding some std::cout to each destructor
};
int main()
{
CBase *ptr1 = new CBase;
CBase *ptr2 = new CChild;
ptr1->vfunc(); // ptr1 points to an instance of CBase. This is what's important!!
ptr2->vfunc(); // ptr2 points to an instance of CChild, which can be referenced to as a CBase
delete ptr1;
delete ptr2;
}
输出:
CBase::vfunc()
CChild::vfunc()
PS:我才意识到我是5年左右迟到了,但因为我对这个发现教育价值,我会反正它张贴!