如何通过基类指针调用派生类的虚函数

时间:2012-08-10 18:46:27

标签: c++ inheritance pointers virtual base

让我们看看这段代码:

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) - &GT; CChild :: vfunc();

4 个答案:

答案 0 :(得分:6)

这不是它的工作原理 - 这是:

CBase *pBase = new CChild;
pBase->vfunc();

virtual函数调用在指针上动态解析&amp;引用(除非您明确地调用该方法,就像您所做的那样)。这意味着你告诉编译器指针是什么并不重要,它将在vftable中查找方法。在您的情况下,vftableCBase

答案 1 :(得分:5)

你做不到。 *pBaseCBase类型的对象。您不能将其视为CChild,因为它不是CChild对象。

使用强制转换为CChild*获得的指针会导致程序出现未定义的行为。

答案 2 :(得分:2)

其他答案提出重点 - 补充:如果您实际上可能正在处理CChild(例如,它是作为参数传递的引用),那么您可以使用dynamic_cast来沮丧。但是,高度依赖dynamic_cast通常表明你的设计出了问题。

演员表的细节可以在这里找到: http://msdn.microsoft.com/en-us/library/cby9kycs(v=vs.80).aspx

所以这个过程需要通过CBaseCChild参数转换为dynamic_cast,如果引用是CChilddynamic_cast成功,那么你可以确保您正在处理CChild,然后您可以安全地将其用作CChild

答案 3 :(得分:1)

这里的问题似乎很简单。 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年了,但是因为我发现了这方面的教育价值,所以我会发布它!