Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the base class method called if the derived class overrides the method?

consider the following program:

class Base {
public:
    virtual void foo() const {
        cout << "Base::foo()" << endl;
    }
};

class Derived : public Base {
public:
    virtual void foo() {
        cout << "Derived::foo()" << endl;
    }
};

void func(Base& obj) {
    obj.foo();
}

void main() {
    Derived d;
    func(d); // Base::foo() is printed 
}

If I remove the const from the Base class foo method then Derived::foo() is called. I can't seem to understand this behavior.

1) What is the reason for this behavior?

2) Is this decided at compile time or runtime?

Thanks

like image 727
dankilman Avatar asked Jun 10 '11 15:06

dankilman


People also ask

How the base class method overrides derived class methods?

An override method is a new implementation of a member that is inherited from a base class. The overridden base method must be virtual, abstract, or override. Here the base class is inherited in the derived class and the method gfg() which has the same signature in both the classes, is overridden.

What will happen if we call a derived class function overridden through a base class object?

Function Overriding in C++ It redefines a function of the base class inside the derived class, which overrides the base class function. Function overriding is an implementation of the run-time polymorphism. So, it overrides the function at the run-time of the program.

Why would you overwrite a method of base class?

The main advantage of method overriding is that the class can give its own specific implementation to a inherited method without even modifying the parent class code.

How can you call the base class method from inside of its overridden method?

Calling Parent class's overridden method from Child class's method using super keyword. from Derived class function will call base class version of display() function i.e.


3 Answers

You aren't overriding the method, since Derived::foo isn't exactly the same.

To override a method, the base and overridden versions must be identical, including const-ness.

like image 20
SLaks Avatar answered Nov 15 '22 06:11

SLaks


In the derived class, the function signature is this:

virtual void foo(); //Derived::foo

which doesn't mention const. Its a non-const member function, while the Base::foo is a const member function. They're two different functions, because const is a part of the function signature.

virtual void foo() const; //Base::foo 

Derived class does NOT override this function, instead it adds another function.

So the fix is this:

class Derived : public Base {
public:
    virtual void foo() const {
        cout << "Derived::foo()" << endl;
    }
};

As const is a part of the function signature. So you must mention it when you intend to override base's foo.


@davka's asked:

so why the const version is selected over the non-const? Is there any rule or it just happened to be the first option?

Its because the static type of obj is Base, and function name is resolved based on the static type of object. Base doesn't even have non-const version. So there is no question of it being selected or rejected. It doesn't exist in Base to begin with.

void func(Base& obj) {
    obj.foo();  //calls Base::foo
}

However, if you change the above code to the following:

void func(Derived & obj) {
    obj.foo();  //calls Derived:foo
}

Now non-const version will be selected, because Base::foo is hidden in Derived class.


Since Derived::foo hides the Base::foo, so you cannot call the latter using an instance of Derived.

Now, lets unhide Base::foo and do some more experiments.

class Derived : public Base {
public:
    using Base::foo;         //<----------------this unhides Base::foo
    virtual void foo() {
        cout << "Derived::foo()" << endl;
    }
};

Now in Derived, both functions (const as well as non-const version) are available, unhidden. Now few interesting questions.

Since now Derived has both functions unhidden, which function will be called in each function below?

void f(Derived& obj) {
    obj.foo(); //Which function? Base::foo or Derived::foo?
}
void g(const Derived & obj) {
    obj.foo(); //Which function? Base::foo or Derived::foo?
}

First one will call Derived::foo which is non-const version, and second one will call Base::foo which is const version. The reason is simple, with const object, only const functions can be invoked, but with non-const objects, both can be invoked, however non-const version is selected if its available.

See online demo : http://www.ideone.com/955aY

like image 168
Nawaz Avatar answered Nov 15 '22 06:11

Nawaz


In C++, you can have two functions with the same name and the same parameters, where the only difference that one is const and one is not.

The idea is that you sometimes want different behaviors. For example, an access function function might have different return types:

class MyClass
{
public:
  virtual Xxx * GetXxx();
  virtual Xxx const * GetXxx() const;
  // ....
}

You can override these functions individually.

In your case, as you call foo from a non-const object, you called the non-const variant of the function. As you had overridden the const-variant, the one in the base class is the one being called.

like image 27
Lindydancer Avatar answered Nov 15 '22 05:11

Lindydancer