How to call virtual function of derived class through base class pointer

早过忘川 提交于 2019-12-22 05:59:27

问题


Let's see this code:

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;
}

The output is:

CBase::vfunc()

But I want to see: CChild::vfunc()

Explicit ((CChild*)pBase) casts to type "CChild*". So why to call derived vfunc() I need replace "important" string with: ((CChild*)pBase)->CChild::vfunc();


回答1:


That's not how it works - this is:

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

virtual function calls are resolved dynamically on pointers & references (unless you call the method explicitly, like you did). Which means it doesn't matter what you tell the compiler the pointer is, it will look for the method in the vftable. Which, in your case, is the vftable of CBase.




回答2:


You can't. *pBase is an object of type CBase. You cannot treat it as if it were a CChild because it isn't a CChild object.

Use of the pointer obtained by the cast to CChild* causes your program to exhibit undefined behavior.




回答3:


the other answers make important points -- to supplement: if you may in fact be dealing with a CChild (e.g. it is a reference passed as a parameter), then you can use dynamic_cast to downcast. however, high reliance on dynamic_cast is often an indication your design has gone wrong.

detail on the cast can be found here: http://msdn.microsoft.com/en-us/library/cby9kycs(v=vs.80).aspx

so the process would entail casting the CBase parameter to CChild via dynamic_cast, if the reference is a CChild and dynamic_cast succeeds, then you could be sure you are dealing with a CChild and you could then safely use it as a CChild.




回答4:


The problem here seems very simple. CBase can not magically upgrade to CChild! Let me rewrite your example and add some comments. It should be self explanatory...

#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;
}

Output:

CBase::vfunc()
CChild::vfunc()

PS: I just realised I'm about 5 years late to the party, but since I find educational value on this I'll post it anyways!



来源:https://stackoverflow.com/questions/11907507/how-to-call-virtual-function-of-derived-class-through-base-class-pointer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!