views:

187

answers:

3

I have a class like so:

class A
{
   public:
      virtual void foo() { bar() }

   protected:  
      virtual void bar() { /* do stuff */ }
}

Now I want a derived class B that overrides both foo and bar. So I wrote the following:

class B : public A 
{
    public: 
        virtual void foo() { A::foo(); /* then other stuff */ }

    protected:
       virtual void bar() { /* do different stuff */ }
}

Everything compiles but when I invoke B::foo I expect B::bar to get (eventually) called. Instead, I get A::bar. What am I doing wrong?

+2  A: 

before the update by the op.

This should work

A* b = new B();

b->bar(); //Notice that this is just an example

Also works with references

void B::foo(){this->bar();}

  B b;
  A& ab = b;
  ab.foo(); //calls B::bar()
Tom
Your update doesn't make any sense. If he *were* calling `A::bar` explicitly, this would be correct (although the `this->` is still superfluous), however take another look at his code: he's calling `A::foo` explicitly, which in turn calls `bar()` normally. Since `bar` is virtual, this should resolve to `B::bar` as he expects.
Tyler McHenry
ok then im taking it out
Tom
b->bar() will not work as the member is protected. Your re-definition of B::foo() is not what the OP wants. He wants it to call the base implementation of A::foo() first.
Martin York
@Martin, it was written before the example given by the op. The first snippet of code was writen to show the point about pointers.
Tom
+9  A: 

Everything compiles but when I invoke B::foo I expect B::bar to get (eventually) called. Instead, I get A::bar. What am I doing wrong?

Looks like you didn't really understand what went wrong in your original code, decided that the virtual override mechanism must be the culprit and then you posted a non-working example which describes what you are inclined to believe, but which you didn't bother to check, because if you had then you'd seen that it does not expose the described behavior. here's a compileable version of your example.

#include <stdio.h>
class A
{
   public:
      virtual void foo() { puts("A:foo()"); bar(); }

   protected:  
      virtual void bar() { puts("A:bar()"); }
};

class B : public A 
{
    public: 
        virtual void foo() { puts("B:foo()"); A::foo(); }

    protected:
       virtual void bar() {  puts("B:bar()");  }
};


int main()
{
    B b;
    b.foo();
}

When I run this I get:

$ g++ g++ h.cc
$ ./a.out
B:foo()
A:foo()
B:bar()

So everything's fine with B::bar().

Luther Blissett
Indeed. The problem is either with the code that creates the object and calls the function (which we haven't been shown), or with the interpretation of the results.
Mike Seymour
A: 

Other than the missing semicolons at the end of the class definitions, the current OP code works as intended.

Jess