Question

I have a class that contains some functions (none are virtual) and 2 more classes publicly inherit that class. In both the sub classes I override the same function of the base class.

After creating objects of all three classes in main (located at the same file), I call the original function with the baseclass object and the overridden functions with the derivedclass objects.

I was expecting all 3 function calls to run the original function from the base class (since I didn't use 'virtual' anywhere in the code), but I actually get each version of that function working according to the class in which it was defined (3 different versions).

I have the classes Base & Derived as follows:

struct Base
{
   void foo();
};

struct Derived : Base
{
   void foo();
};

in main:

int main()
{
   Derived d;
   d.foo();
}

I thought d.foo() should run Base::foo() if not using 'virtual'.

Was it helpful?

Solution

This is not "overriding"... and it doesn't need to be.

struct Base
{
   void foo();
};

struct Derived : Base
{
   void foo();
};

int main()
{
   Derived d;
   d.foo();
}

If I understand you correctly, then you were expecting this to execute Base::foo(), because the functions are not virtual and therefore one does not override the other.

But, here, you do not need virtual dispatch: the rules of inheritance simply state that you'll get the right function for the type of the object you run it on.

When you need virtual dispatch/overriding is a slightly different case: it's when you use indirection:

int main()
{
   Base* ptr = new Derived();
   ptr->foo();
   delete ptr;
}

In the above snippet, the result will be that Base::foo() is called, because the expression ptr->foo() doesn't know that *ptr is really a Derived. All it knows is that ptr is a Base*.

This is where adding virtual (and, in doing so, making the one function override the other) makes magic happen.

OTHER TIPS

You cannot override something that isn't virtual. Non-virtual member functions are dispatched statically based on the type of the instance object.

You could cheat by "overriding" a function by making it an inline function calling something indirectly. Something like (in C++03)

 class Foo;
 typedef int foo_sig_t (Foo&, std::string&);
 class Foo {
    foo_sig_t *funptr;
 public:
    int do_fun(std::string&s) { return funptr(*this,s); }
    Foo (foo_sig_t* fun): funptr(fun) {};
    ~Foo () { funptr= NULL; };
    // etc
 };

 class Bar : public Foo {
    static int barfun(Bar&, std::string& s) { 
       std::cout << s << std::endl;
       return (int) s.size();
    };
  public: 
    Bar () : Foo(reinterpret_cast<foo_sig_t*>)(&barfun)) {};
     // etc...
  };

and later:

  Bar b;
  int x=b.do_fun("hello");

Officially this is not overloading a virtual function, but it looks very close to one. However, in my above Foo example each Foo instance has its own funptr, which is not necessarily shared by a class. But all Bar instances share the same funptr pointing to the same barfun.

BTW, using C++11 lambda anonymous functions (internally implemented as closures), that would be simpler and shorter.

Of course, virtual functions are in generally in fact implemented by a similar mechanism: objects (with some virtual stuff) implicitly start with a hidden field (perhaps "named" _vptr) giving the vtable (or virtual method table).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top