Question

I'm trying to understand when/where exactly one should write the 'virtual' keyword in order for any descendant of a given class to enable polymorphic behavior, since I could not find specific informations about this question elsewhere.

For what I've tried, having virtual on a function in the base class automatically makes that function virtual for any descendants. However many snippets around the Internet often declare these functions again virtual in the descendants.

struct A {
    virtual void foo1() { std::cout << "[A] foo1.\n"; }
    virtual void foo2() { std::cout << "[A] foo2.\n"; }
};
struct B : public A {
    virtual void foo1() { std::cout << "[B] foo1.\n"; }
            void foo2() { std::cout << "[B] foo2.\n"; }
};

Compiling this code with g++ I get that both foo1 and foo2 have polymorphic behavior. In addition, even if I derive again from B and create a C class, and I implement foo2 again without the virtual keyword, foo2 still uses the v-table.

Is using the virtual keyword in derived classes only used for clarity and self-documentation, or is there some other effect that I'm not aware of?

Was it helpful?

Solution

For what I've tried, having virtual on a function in the base class automatically makes that function virtual for any descendants.

This is true, the child automatically inherits the virtualness of the parent method.

People restate virtual in child classes as a convention simply to explicitly show that the child intends to override a virtual method (we have override in C++11 though).

OTHER TIPS

Points to note:

  1. Any method that is declared virtual is dynamically bound (run-time). Any other method is statically bound (compile-time).

  2. Any method once declared virtual, remains virtual for all the levels of inheritance below regardless of whether or not it is declared virtual in the classes below. i.e. Suppose the hierarchy is this: Man->Indian->Tamilian.

If do_work() is a virtual method, then it remains virtual even for Tamilian, even if it is declared as virtual only in Man.

How does the virtual keyword work?

Declaring do_work() as virtual simply means: which do_work() to call will be determined ONLY at run-time.

Suppose I do,

Man *man;
man = new Indian();
man->do_work(); // Indian's do work is only called.

If virtual is not used, the same is statically determined or statically bound by the compiler, depending on what object is calling. So if an object of Man calls do_work(), Man's do_work() is called EVEN THOUGH IT POINTS TO AN INDIAN OBJECT

To my astonishment I discovered that purely virtual functions can also have a body! I thought they can't. But, the truth is that they can. Which means an abstract class' pure virtual function can be called!!! Two very good authors are Bjarne Stroustrup and Stan Lippman.... because they wrote the language.

Unless you intend for it to be derived, there is no particular reason why a child class should have the virtual keyword on a member.

The decision whether or not to make a member of your class members virtual only depends on how you intend your class to be derived. If you're not intending your class to be derived, then no

For a more complete explanation, consider the following code. If I now intend to derive off B, or to make B a reusable piece of code, I might make the code break by blocking access to A's members.

   #include <iostream>

class A
{
public:
  virtual void foo1()
  {
    std::cout<<"A.foo1"<<std::endl;
  }
  void foo2()
  {
    std::cout<<"A.foo2"<<std::endl;
  }
};

class B : public A
{
public:
  void foo1()
  {
    std::cout<<"B.foo1"<<std::endl;
  }
  void foo2()
  {
    std::cout<<"B.foo2"<<std::endl;
  }
};


int main()
{
  A* a = new A();
  a->foo1();
  a->foo2();
  B* b = new B();
  b->foo1();
  b->foo2();
  delete a;
  a=b;
  a->foo1();
  a->foo2();
}

which produces the output:

A.foo1
A.foo2
B.foo1
B.foo2
B.foo1
A.foo2
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top