6

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();

LEXX
  • 106
  • 1
  • 5

4 Answers4

6

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.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
5

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.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • 1
    So how to understand Schildt H.: "a base class pointer can also be used as a pointer to an object of any class derived from that base". – LEXX Aug 10 '12 at 19:00
  • And so why the string ((CChild*)pBase)->CChild::vfunc() works? – LEXX Aug 10 '12 at 19:06
  • @LEXX: First, you should burn that book and get [a good introductory book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). What he says in that quote is correct, though. A base class pointer (`CBase*`) can point to an object of a type derived from `CBase` (like `CChild`). That's not what you've done, though: your base class pointer points to a base class object. If you had, for example, `CBase* p = new CChild();`, then `p` would be a base class pointer pointing to an object of a derived class. – James McNellis Aug 10 '12 at 19:32
  • 1
    @LEXX: The expression doesn't work. It appears to "work," but it could just as easily cause your program to crash, or to cause your computer to burst into flames. Your program exhibits undefined behavior, which means it can do anything. – James McNellis Aug 10 '12 at 19:33
2

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.

justin
  • 104,054
  • 14
  • 179
  • 226
1

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!

NicoBerrogorry
  • 446
  • 4
  • 15