tags:

views:

57

answers:

2

Consider the following source code. I have two classes CBar and CFoo. CFoo inherits from CBar. The output of this source code is

Bar 
Foo 
Bar 

I was expecting

Bar 
Foo 
Foo

Where did I go wrong? What I was thinking was that since the CFoo object has a Speak function that overrides the CBar speak function. When I call The Speak() function from a CBar function on an object that is CFoo the CFoo Speak function would be executed. But that assumption appears to be wrong.

class CBar
{
    public:
        void Speak() { 
            printf(" Bar \n"); 
        }

        void DoStuff() {
            this->Speak(); 
        }
};


class Cfoo : public CBar 
{
    public:
        void Speak() { 
            printf(" Foo \n"); 
        }

        void DoStuff() {
            CBar::DoStuff(); 
        }
};



int _tmain(int argc, _TCHAR* argv[])
{
    CBar b;
    b.Speak(); 

    Cfoo f;
    f.Speak();

    f.DoStuff(); 
    return 0;
}
+3  A: 

In C++, you need to use virtual to enable polymorphism. Otherwise, all Speak() is doing in CFoo is hiding Speak() in CBar.

class CBar 
{ 
    public: 
        virtual void Speak() {  // Note virtual keyword
            printf(" Bar \n");  
        } 

        void DoStuff() { 
            this->Speak();  
        } 
}; 


class Cfoo : public CBar  
{ 
    public: 
        void Speak() {  // Overrides the virtual method Speak()
            printf(" Foo \n");  
        } 

        void DoStuff() { // Hides CBar::DoStuff() method
            CBar::DoStuff(); 
        } 
}; 



int _tmain(int argc, _TCHAR* argv[]) 
{ 
    CBar b; 
    b.Speak();  

    // Speak() is a virtual function, so calling Speak() on a CFoo or
    // a CBar pointer will call the most derived implementation of Speak(). 
    Cfoo f; 
    f.Speak(); 

    /* My example */
    // Since CFoo "is-a" CBar, this conversion is safe.
    CBar* bar = &f;
    // Since Speak() is a virtual function, this will call CFoo's implementation
    // of Speak(), not CBar's.
    bar->Speak();
    /* End example */

    // Because CBar::DoStuff() is hidden, this calls CFoo::DoStuff() instead.
    f.DoStuff();
    return 0; 
} 
In silico
Thank you, I knew it was going to be something simple.
Steven smethurst
+3  A: 

Speak is not a polymorphic function.

That is, because it isn't marked virtual any calls to it are determined statically. So within CBar, this->Speak(); will always refer to CBar::Speak.

If you make the function virtual, a call to the function will be chosen based off the dynamic type, not the static type, and the call you expect will be made.

GMan