22
class Base
{
   public:
   virtual void func() const
   {
     cout<<"This is constant base "<<endl;
   }
};

class Derived : public Base
{
   public:
   virtual void func()
   {
     cout<<"This is non constant derived "<<endl;
   }
};


int main()
{
  Base *d = new Derived();
  d->func();
  delete d;

  return 0;
}

Why does the output prints "This is constant base". However if i remove const in the base version of func(), it prints "This is non constant derived"

d->func() should call the Derived version right, even when the Base func() is const right ?

vamsi
  • 1,727
  • 3
  • 22
  • 25
  • Possible duplicate of http://stackoverflow.com/questions/7504300, http://stackoverflow.com/questions/3827374, and http://stackoverflow.com/questions/4152799. – In silico Feb 28 '12 at 19:12
  • possible duplicate of [virtual function that is const in the base class and not const in the derived](http://stackoverflow.com/questions/7504300/virtual-function-that-is-const-in-the-base-class-and-not-const-in-the-derived) – Mooing Duck Feb 28 '12 at 19:58

3 Answers3

43
 virtual void func() const  //in Base
 virtual void func()        //in Derived

const part is actually a part of the function signature, which means the derived class defines a new function rather than overriding the base class function. It is because their signatures don't match.

When you remove the const part, then their signature matches, and then compiler sees the derived class definition of func as overridden version of the base class function func, hence the derived class function is called if the runtime type of the object is Derived type. This behavior is called runtime polymorphism.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • I am confused here. If both are treated as 2 different functions, why does the d->func() call the derived version, as there is no const applicable here. – vamsi Feb 28 '12 at 19:15
  • 1
    Right. And in fact it's quite common for a class to define two identical functions, one `const` and one not. – Mark Ransom Feb 28 '12 at 19:16
  • 2
    @vamsi, the definition of `Base` only contains one function, so that's the one that's called. – Mark Ransom Feb 28 '12 at 19:17
  • 3
    @vamsi Because you have a pointer to Base*. In the Base interface, there is only one overload of 'func' available, and that's read-only (const). The fact that it's read-only is irrelevant when it's the only one the compiler will see through a base pointer. If both functions were defined in Base, then naturally the compiler would choose the non-const one. The derived one isn't even available to call in this context. – stinky472 Feb 28 '12 at 19:19
  • 5
    Weighing in on an old question incase people find this. With C++11 now remember to add `override` to all the functions you expect to actually override and the compiler will tell you when they don't, like in this case. – Mike Vine May 15 '13 at 08:30
  • the actual object pointed by d is for class 'Derived'. Why isnt the vtable containing the methods corresponding to those? If yo uhave a const and a non const function, the vtable shows entries corresponding to both the functions in vtable. Why isnt it in this case? – Abhinav Jul 24 '15 at 10:55
  • @Abhinav the vtable *does* have both functions but the pointer is of type `Base *` so only *one* of them can be reached, because the definition of `Base` only contains one function. If the function signatures matched then both functions would be in a single vtable entry and the function would be properly polymorphic. – Mark Ransom Apr 15 '16 at 21:23
5

virtual void func() is actually of a different signature than virtual void func() const. Thus you didn't override your original, read-only base function. You ended up creating a new virtual function instead in Derived.

You can also learn more about this if you ever try to create pointers to member functions (PTMFs), but that's a rare necessity (might be good for study or practice, however).

The override keyword in C++11 is particularly handy to help avoid these kinds of mistakes. The compiler would then tell you that your definition of 'func' in derived does not override anything.

stinky472
  • 6,737
  • 28
  • 27
4

No, because virtual void func() is not an override for virtual void func() const.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680