Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why must we declare virtual methods as such

Tags:

c++

oop

Suppose we have a class, "Animal", and subclasses, "Cat" and "Dog".

Let's say we want to allow both "Cat" and "Dog" to make a noise (cat: "meow" - dog: "woof") when we pass their objects into an intermediate function for any "Animal".

Why must we use a virtual method to do this? Couldn't we just do Animal->makeNoise() without defining a virtual method in "Animal"? As "Cat" and "Dog" are both animals, wouldn't it be clear that "makeNoise()" is referring to the Animal which has been passed to the function?

Is this just a matter of syntax or something more? I'm pretty sure in Java we don't have to do this.

like image 322
M-R Avatar asked May 03 '16 16:05

M-R


3 Answers

In Java, all member functions are virtual by default (except static, private, and final ones).

In C++, all member functions are non-virtual by default. Making functions virtual adds overhead - both runtime and to object size - and the C++ philosophy is don't pay for what you don't use. Most of my objects are not polymorphic, so I shouldn't have to pay for polymorphism unless I need it. Since you need Animal::makeNoise() to be virtual, you must explicitly specify it as such.

like image 155
Barry Avatar answered Nov 19 '22 22:11

Barry


C++ is designed to run with as little overhead as possible, trusting the programmer to make the correct call. Essentially, it 'gives you the gun and the option to shoot yourself in the foot', as one of my friends likes to say often. Speed and flexibility are paramount.

To correctly cause true polymorphic behavior, C++ requires it be specified. However! It is only required to be specified in the base class, as all derived class will inherit the virtual member functions. If a member inherits a virtual member function, it is good practice to place 'virtual' in the declaration, but not required.

ADTs usually implement pure virtual functions to indicate that the derived classes MUST implement the function. Such as:

animal makeNoise() = 0; /*Indicates this function contains no implementation.
and must be implemented by derived classes in order to function.*/

Again, it is not required the derived classes include 'virtual' in their inherited members so long as the base class includes this.

like image 35
NonCreature0714 Avatar answered Nov 19 '22 22:11

NonCreature0714


If you want to deduce the type of the Animal and then call make_sound(), then you would have to do a dynamic_cast on the animal object for each and every child of animal. This would include any class that is directly or indirectly a child of the Animal class.

This is both difficult to maintain and very painful to any change eg. Adding new class as a child to the Animal class.

Since c++ philosophy is efficiency, you will have to ask the compiler to provide you with run-time polymorphism as it is costly. How would you do that? By stating the make_sound() function as virtual. This creates a vtable ( a table of functions pointers ) which refers to an address of make_sound() which differs to based on the type of the object.

No need to downcast as indirection handles everything for you. What could be hundreds of lines of code is just a single line of code. That is the power of indirection!!

like image 36
Abdus Khazi Avatar answered Nov 19 '22 21:11

Abdus Khazi