-1

Okay, so I know there are a lot of polymorphism threads flying around but I have yet to encounter this situation.

class Base {
public:
    virtual void method1() {
        cout << "BaseMethod1" << endl;
    }

    void method2() {
        cout << "BaseMethod2" << endl;
    }
};

class Derive: public Base {
public:
    void method1() {
        cout << "DeriveMethod1" << endl;
        method2();
    }

    void method2() {
        cout << "DeriveMethod2" << endl;
    }
};

int main() {
    Base* p = new Derive();
    p->method1();
}

What's tripping me up is method1 in the derived class calls a method2. So which method2 would it be since the method2 in the Base class wasn't declared as virtual?

Thanks ahead of time!

Jason Larke
  • 5,289
  • 25
  • 28
knguyen2525
  • 95
  • 1
  • 8
  • 2
    `method2()` parenthesis are missing if I am not wrong – Grijesh Chauhan Mar 01 '13 at 04:55
  • 1
    @Pubby trying things won't necessarily lead to enlightenment in C++. In fact it can lead to a dangerous false sense of security in the case of undefined behavior that happens to work. – Antimony Mar 01 '13 at 04:56
  • 6
    The key phrase you want to look up to answer this question is ["name hiding"](http://www.parashift.com/c++-faq-lite/hiding-rule.html). – In silico Mar 01 '13 at 04:56
  • -1. Do a basic research first since this is a very basic question, ask the compiler, then perhaps ask a more specific question. – Lie Ryan Mar 01 '13 at 04:59
  • 1
    @Antimony well if you prefer to read the standard then have it your way. All I care is that people do a little research before asking questions. – Pubby Mar 01 '13 at 04:59
  • possible duplicate of [Virtual function calling a non-virtual function](http://stackoverflow.com/questions/8796626/virtual-function-calling-a-non-virtual-function) – jogojapan Mar 01 '13 at 05:04
  • Thanks for the quick responses! It makes sense now! And sorry for the sloppy syntax; I wrote this kinda on the fly and was just hoping to get the gist of what I wanted across. Thanks again. – knguyen2525 Mar 01 '13 at 05:05

3 Answers3

4

The code in question will not compile because Base::method1() is declared private. It needs to be public to be able to be called from main.


Derived::method1() is implicitly virtual even if not marked as virtual. So the this in Derived::method1() points to a Dervied object and in this scope compiler can only see Derived::method2(). Hence Derived::method2() will be called. The method in derived class hides the same named method in Base class.


Good Read:

What's the meaning of, Warning: Derived::f(char) hides Base::f(double)?

Alok Save
  • 202,538
  • 53
  • 430
  • 533
2

The main reason you do not see this pattern very often is that it is in fact an anti-pattern.

The Derived method will be invoked because you are calling it with a Derived object reference (this). If you were calling it with a Base class reference you will get the Base method.

If you redeclare a non-virtual method you are hiding the base method and breaking polymorphism.

Matthew Sanders
  • 4,875
  • 26
  • 45
  • +1 for several good points (especially significance of `this`), but regarding "redeclare a non-virtual method [is] breaking polymorphism" - that's a bit melodramatic: the object may continue to work polymorphically through a Base class reference/pointer perfectly well - as per Liskov Substitution Principle - or it may even be necessary not to have some functions virtual to avoid breaking the principle (e.g. a Derived class serialisation method that wasn't reparsable as per Base method documentation). Not broken, but fragile (e.g. harder to switch to compile-time polymorphism). – Tony Delroy Mar 01 '13 at 05:59
  • Good point. There are almost always exceptions to the rule. I tend to stick with this particular rule pretty heavily as it reduces the likelihood of error in large code bases. This is a contradiction to what one would expect. I guess you could say it inflates polymorphism because now you are making an object that takes many forms based on how you refer to it :P. – Matthew Sanders Mar 01 '13 at 06:23
1

It will use Derive::method2() as name look-up (in body of Derive::method1()) starts from the class itself.

c-smile
  • 26,734
  • 7
  • 59
  • 86