What is the purpose of virtual member functions?
Asked Answered
B

10

12

What is the difference member between function overriding and virtual functions in C++?

Virtual member functions can be overridden in derived classes. Redefining a function in a derived class is called function overriding.

Why do we actually have virtual functions?

Barmen answered 10/2, 2010 at 17:27 Comment(14)
Which book are you learning C++ from?Orgeat
There isn't a difference between method overriding and virtual functions. There is a difference between overloading and overriding. Is that what you want to know?Scribble
You are asking a question that sounds like "what is the difference between a car and a sandwich?". There's no meaningful "difference" between these concepts. They are not related in any way that would justify a question about some "difference" between them. In order to even start answering your question one needs to understand first how such a weird question could arise. Care to elaborate?Admissive
@andrey, @neil, why are u so hostile ??Truancy
@erick2red, I agree... The guy is a beginner... People need to calm down...Mozell
@erick2red: Hostile? I'm not hostile at all. What I said is perfectly neutral and to the point. I understand that some people might prefer higher amount of backpatting and sugary compliments in their conversations, but at the same time I believe that in a technical forum this is not mandatory.Admissive
@erick2red: Moreover, when I say that "one needs to understand first how such a weird question could arise" it is not just a rhetorical remark or a veiled insult. I do really want to know how this question came to be, because it is indeed the best (or actually the only) way to get to the root of the OP's confusion.Admissive
@AndreyT: The question does say "virtual function concepts", which does include which function is called when. It isn't very well phrased, but it looks clear to me.Deborahdeborath
@andrey My point is simple the guy is just a C++ beginner, i mean a programmer beginner cause concepts like those are not c++ related, those concepts belongs to language semantics. So i think he was trying to get the difference between both concept in C++ practically. So i ask you about being so hostile because i think you tried to over explain something simple, just that.Truancy
@erick2red: From what I can tell, rainbows and bunnies might seem hostile to you. Seriously, all Neil did was ask a simple question and Andrey just made a matter-of-fact explanation. People need to wake up and realize not everyone's out to get you; some of us just want to communicate information without having to side-step every little insecurity people have.Hegumen
IMHO, the question SHOULD be why does C++ have NON-virtual methods. virtual methods are the way that inheritance is SUPPOSED to behave... (in theory)Elbertelberta
Vjay, please pick one of the answers and mark it as the answer so that this question will appear as answered. There are some nice details in the answers here. This question does not seem to show in Google search results. I assume because it is still marked as unanswered.Sunroom
Virtual functions are indeed confusing to anyone new to C++. Most books do not explain it properly either. Hope this helps: nrecursions.blogspot.com/2015/06/…Brasca
Related: https://mcmap.net/q/45145/-why-do-we-need-virtual-functions-in-c/5740428Pocosin
J
3

ABSTRACT

In this paper, we discuss virtual functions in C++. Part zero explains how virtual functions are declared and overridden. Part one attempts (and perhaps fails) to explain how virtual functions are implemented. Part two is a sample program that uses the example classes defined in parts zero and one. Part three is the classic animal example given in every virtual function - polymorphism tutorial.

PART ZERO

A method of a class is said to be virtual if and only if its declared to be so.

class my_base
{
public:
            void non_virtual_test() { cout << 4 << endl; } // non-virtual
    virtual void virtual_test()     { cout << 5 << endl; } // virtual
};

(Of course, I am assuming the programmer did not previously do anything like #define virtual.)

A class that redeclares and re-implements a non-virtual method of one of its bases is said to overload that method. A class that redeclares and re-implements a virtual method of one of its bases is said to override that method.

class my_derived : public my_base
{
public:
    void non_virtual_test() { cout << 6 << endl; } // overloaded
    void virtual_test()     { cout << 7 << endl; } // overriden
};

PART ONE

When the compiler detects a class has virtual methods, it automatically adds a virtual method table (also known as vtable) to the class' memory layout. The result is similar to what would have been generated from compiling this code:

class my_base
{
//<vtable>
// The vtable is actually a bunch of member function pointers
protected:
    void (my_base::*virtual_test_ptr)();
//</vtable>

// The actual implementation of the virtual function
// is hidden from the rest of the program.
private:
    void virtual_test_impl() { cout << 5 << endl; }

// Initializing the real_virtual_test pointer in the vtable.
public:
    my_base() : virtual_test_ptr(&my_base::virtual_test_impl) {}

public:
    void non_virtual_test() { cout << 4 << endl; }
    // The interface of the virtual function is a wrapper
    // around the member function pointer.
    inline void virtual_test() { *virtual_test_ptr(); }
};

When the compiler detects a class has overridden a virtual method, it replaces its associated entry in the vtable. The result is similar to what would have been generated from compiling this code:

class my_derived : public my_base
{
// The actual implementation of the virtual function
// is hidden from the rest of the program.
private:
    void virtual_test_impl() { cout << 7 << endl; }

// Initializing the real_virtual_test pointer in the vtable.
public:
    my_derived() : virtual_test_ptr(&my_derived::virtual_test_impl) {}

public:
    void non_virtual_test() { cout << 6 << endl; }
};

PART TWO

Now that it's clear that virtual functions are implemented using vtables, which are nothing but a bunch of function pointers, it should be clear what this code does:

#include <iostream>

using namespace std;

class my_base
{
    public:
            void non_virtual_test() { cout << 4 << endl; }
    virtual void virtual_test()     { cout << 5 << endl; }
};

class my_derived : public my_base
{
public:
    void non_virtual_test() { cout << 6 << endl; }
    void virtual_test()     { cout << 7 << endl; }
}

int main()
{
    my_base* base_obj = new my_derived();

    // This outputs 4, since my_base::non_virtual_test() gets called,
    // not my_derived::non_virtual_test().
    base_obj->non_virtual_test();

    // This outputs 7, since the vtable pointer points to
    // my_derived::virtual_test(), not to my_base::virtual_test().
    base_obj->virtual_test();

    // We shall not forget
    // there was an object that was pointed by base_obj
    // who happily lived in the heap
    // until we killed it.
    delete base_obj;

    return 0;
}

PART THREE

Since no virtual function example is complete without an example with animals...

#include <iostream>

using namespace std;

class animal
{
public:
    virtual void say_something()
    { cout << "I don't know what to say." << endl
           << "Let's assume I can growl." << endl; }

    /* A more sophisticated version would use pure virtual functions:
     *
     * virtual void say_something() = 0;
     */
};

class dog : public animal
{
public:
    void say_something() { cout << "Barf, barf..." << endl; }
};

class cat : public animal
{
public:
    void say_something() { cout << "Meow, meow..." << endl; }
};

int main()
{
    animal *a1 = new dog();
    animal *a2 = new cat();
    a1->say_something();
    a2->say_something();
}
Jaunitajaunt answered 11/2, 2010 at 2:31 Comment(0)
A
12

Virtual function / method is simply a function whose behavior can be overriden within a subclass (or in C++ terms a derived class) by redefining how the function works (using the same signature).

Think of a base class mammal with a speak function. The function is void and simply couts how a mammal speaks. When you inherit from this class you can override the speak method so that dogs go "Arf Arf!" and cats go "Meow Meow".

Your question seems to ask what are the differences, well there are none because with virtual functions one can override the behavior of these functions. You may be after the difference between overriding functions and overloading them.

Overloading functions means to create a function with the same name but different arguments i.e. different number- and type-of argument(s). Here is an explanation on overloading in C++ from IBM's site:

Overloading (C++ only) If you specify more than one definition for a function name or an operator in the same scope, you have overloaded that function name or operator. Overloaded functions and operators are described in Overloading functions (C++ only) and Overloading operators (C++ only), respectively.

An overloaded declaration is a declaration that had been declared with the same name as a previously declared declaration in the same scope, except that both declarations have different types.

If you call an overloaded function name or operator, the compiler determines the most appropriate definition to use by comparing the argument types you used to call the function or operator with the parameter types specified in the definitions. The process of selecting the most appropriate overloaded function or operator is called overload resolution, as described in Overload resolution (C++ only).

As for the full rational reason for situations where virtual functions are required, this blog post gives a good one: http://nrecursions.blogspot.in/2015/06/so-why-do-we-need-virtual-functions.html

Alltime answered 10/2, 2010 at 17:35 Comment(2)
In C++ terms "a derived class".Orgeat
one minor nitpick: you say that overloading "means to create a function with the same name but different arguments or return types". I would just remove the "return types" part of that statement...they are not considered part of the overload resolution, at least in the current c++ standard.Kemppe
M
9

The difference between function overriding and virtual function becomes important with polymorphism. Specifically when using references or pointers to a base class.

The Base Setup

In C++, any derived class can be passed to a function requiring a base class object. (See also Slicing and LSP). Given:

struct Base_Virtual
{
  virtual void some_virtual_function();
};

struct Base_Nonvirtual
{
  void some_function();
};

void Function_A(Base_Virtual * p_virtual_base);
void Function_B(Base_Nonvirtual * p_non_virtual_base);

In the above code, there are two base classes, one declares a virtual method, the other declares a non-virtual function.

Two functions are declared that require pointers to the respective base clases.

The Derived Classes

Let us now test the polymorphism, especially virtual vs. non-virtual (overriding methods). The structures:

struct Derived_From_Virtual
: public Base_Virtual
{
  void some_virtual_function(); // overrides Base_Virtual::some_virtual_function()
};

struct Derived_From_Nonvirtual : public Base_Nonvirtual { void some_function(); }

According to the C++ language, I can pass a pointer to a Derived_From_Virtual to Function_A because Derived_From_Virtual inherits from Base_Virtual. I can also pass a pointer to Derived_From_Nonvirtual to Function_B.

The Difference Between virtual and overriding

The virtual modifier in Base_Virtual, tells the compiler that Function_A will use Derived_From_Virtual::some_virtual_function() instead of the method in Base_Virtual. This is because the method is virtual, the final definition may reside in a future or derived class. The actual definition says to use the method in the most derived class containing the definition.

When passing a pointer to Derived_From_Nonvirtual to Function_B, the compiler will instruct the function to use the method of the base class, Base_Nonvirtual::some_function(). The some_function() method in the derived class is a separate, unrelated, method from the base class.

The primary difference between virtual and overriding occurs with polymorphism.

Madwort answered 10/2, 2010 at 20:25 Comment(0)
C
8

Check out C++ FAQ lite, http://www.parashift.com/c++-faq-lite/. is probably one of the best C++ resources for beginners. it has in-depth write-up about virtual functions and overriding.

I personally found C++ FAQ to be an excellent source as I learn C++. Other people have different opinion, your mileage may vary

Consecutive answered 10/2, 2010 at 17:38 Comment(6)
C++ FAQ is not introductory, its a reference.Burchfield
If you don't already know C++, a FAQ telling you how your C++ sucks isn't going to help!Subdivide
@John Dibling, maybe you are confusing the C++FAQ lite with the C++ FQA, the former being a compendium of frequently asked questions in comp.lang.c++, while the later is just a rant against the language based on dubious facts.Replace
@David Rodrigues - dribeas: I think your bias for C++ has skewed your perseption of Yossi Kreinin's writings. I'm a C++ fan myself, and I find yosefk.com way more informative than the parashift.com FAQ.Squarely
@ just somebody. I haven't found a single useful thing in the "fqa". What was informative for you there?Benzoin
The link’s broken?Overlarge
L
4

This is more a follow up on the comments from this answer than an answer by itself.

virtual is a keyword that requests runtime dispatch for the method being declared and at the same time declares the method as one of the overrides (implemented pure virtual methods aside). The method being declared, and any method that shares the exact signature and name in the deriving hierarchy from this class down are overrides. When you call a virtual method through a parent pointer or reference, the runtime will call the most derived override in the hierarchy of the called upon object.

When a method is not virtual, and the same method is defined later on in the hierarchy, you are hiding the parent method. The difference here is that when the method is being called through a base pointer or reference it will be calling the base implementation, while if it is being called in a derived object it will call the derived implementation. This, among other cases, is called hiding because the base and derived functions are unrelated, and having it defined in the derived class will hide the base version from a call:

struct base {
   virtual void override() { std::cout << "base::override" << std::endl; }
   void not_override() { std::cout << "base::not_override" << std::endl; }
};
struct derived : base {
   void override() { std::cout << "derived::override" << std::endl; }
   void not_override() { std::cout << "derived::not_override" << std::endl; }
};
int main() {
   derived d;
   base & b = d;

   b.override();     // derived::override
   b.not_override(); // base::not_override
   d.not_override(); // derived::not_override
}

The difference, and what is wrong in the answer by @erik2red is that overrides are intimately related to virtual functions and imply that there is a runtime dispatch mechanism in place that determines the most derived override to call. The behavior that is shown in the answer and associated to override is actually the behavior when there are no overrides but rather method hiding.

Other issues

The language allows for pure virtual methods with implementation. It does not say anything about what terminology should be used with them, but a pure virtual method will never be considered for runtime dispatch. The reason is that when a classes with pure virtual methods (even if implemented) are considered abstract classes, and you cannot instantiate an object of the class. Once you have a derived class that provides an implementation for that method, that implementation becomes the final override in the hierarchy. The class can now be instantiated, but the pure virtual method will not be called through the runtime dispatch mechanism.

Virtual methods that are not the final override, as well as hided methods can be called if using the fully qualified name. In the case of virtual methods, using the fully qualified name disables the polymorphic dispatch mechanism for the call: d.base::override() will call the base implementation even if there are other overrides in deriving classes.

A method can hide other methods in base classes even if the signatures do not match.

struct base {
   void f() {}
};
struct derived : base {
   void f(int) {}
};
int main() {
   derived d;
   // d.f() // error, derived::f requires an argument, base::f is hidden in this context
}

As with overrides, d.base::f() will call the base version, not because it disables polymorphism --it does not, as the method is not declared virtual it will never have polymorphic behavior-- but because the full qualification tells the compiler where the method is, even if it was hidden by another method in the derived class.

Locality answered 11/2, 2010 at 8:48 Comment(3)
i dbout about an hour before answer this back, i don't disagree with you, the point is your giving strict sense to 'override' word that maybe comes into sense with you, but not to a programmer beginner. By the way, we shouldn't be involved in this fight here. this isn't helpful for anyone but us (both trying to get satisfied)Truancy
The term 'override' is defined in the standard (10.3 [class.virtual]/2), and as such has a strict meaning. Beginners (and not beginners) better learn those term with the meaning that the standard provides, because that is both a tool to interpret the standard and a language of communication with other programmers. Reading your comment (involved in this fight) I want to apologize if you found any part of the comments or the answer offensive, that was clearly not my intention.Replace
I agree here, there is nothing less productive than speaking with someone that attributes another meaning to the words than you do... in the worst case you leave the discussion fully satisfied only to discover later on than they interpreted differently from what you thought... It is thus best, especially for beginners to learn the right term early on, as it's difficult once you have an habit to shed it.Marijn
J
3

ABSTRACT

In this paper, we discuss virtual functions in C++. Part zero explains how virtual functions are declared and overridden. Part one attempts (and perhaps fails) to explain how virtual functions are implemented. Part two is a sample program that uses the example classes defined in parts zero and one. Part three is the classic animal example given in every virtual function - polymorphism tutorial.

PART ZERO

A method of a class is said to be virtual if and only if its declared to be so.

class my_base
{
public:
            void non_virtual_test() { cout << 4 << endl; } // non-virtual
    virtual void virtual_test()     { cout << 5 << endl; } // virtual
};

(Of course, I am assuming the programmer did not previously do anything like #define virtual.)

A class that redeclares and re-implements a non-virtual method of one of its bases is said to overload that method. A class that redeclares and re-implements a virtual method of one of its bases is said to override that method.

class my_derived : public my_base
{
public:
    void non_virtual_test() { cout << 6 << endl; } // overloaded
    void virtual_test()     { cout << 7 << endl; } // overriden
};

PART ONE

When the compiler detects a class has virtual methods, it automatically adds a virtual method table (also known as vtable) to the class' memory layout. The result is similar to what would have been generated from compiling this code:

class my_base
{
//<vtable>
// The vtable is actually a bunch of member function pointers
protected:
    void (my_base::*virtual_test_ptr)();
//</vtable>

// The actual implementation of the virtual function
// is hidden from the rest of the program.
private:
    void virtual_test_impl() { cout << 5 << endl; }

// Initializing the real_virtual_test pointer in the vtable.
public:
    my_base() : virtual_test_ptr(&my_base::virtual_test_impl) {}

public:
    void non_virtual_test() { cout << 4 << endl; }
    // The interface of the virtual function is a wrapper
    // around the member function pointer.
    inline void virtual_test() { *virtual_test_ptr(); }
};

When the compiler detects a class has overridden a virtual method, it replaces its associated entry in the vtable. The result is similar to what would have been generated from compiling this code:

class my_derived : public my_base
{
// The actual implementation of the virtual function
// is hidden from the rest of the program.
private:
    void virtual_test_impl() { cout << 7 << endl; }

// Initializing the real_virtual_test pointer in the vtable.
public:
    my_derived() : virtual_test_ptr(&my_derived::virtual_test_impl) {}

public:
    void non_virtual_test() { cout << 6 << endl; }
};

PART TWO

Now that it's clear that virtual functions are implemented using vtables, which are nothing but a bunch of function pointers, it should be clear what this code does:

#include <iostream>

using namespace std;

class my_base
{
    public:
            void non_virtual_test() { cout << 4 << endl; }
    virtual void virtual_test()     { cout << 5 << endl; }
};

class my_derived : public my_base
{
public:
    void non_virtual_test() { cout << 6 << endl; }
    void virtual_test()     { cout << 7 << endl; }
}

int main()
{
    my_base* base_obj = new my_derived();

    // This outputs 4, since my_base::non_virtual_test() gets called,
    // not my_derived::non_virtual_test().
    base_obj->non_virtual_test();

    // This outputs 7, since the vtable pointer points to
    // my_derived::virtual_test(), not to my_base::virtual_test().
    base_obj->virtual_test();

    // We shall not forget
    // there was an object that was pointed by base_obj
    // who happily lived in the heap
    // until we killed it.
    delete base_obj;

    return 0;
}

PART THREE

Since no virtual function example is complete without an example with animals...

#include <iostream>

using namespace std;

class animal
{
public:
    virtual void say_something()
    { cout << "I don't know what to say." << endl
           << "Let's assume I can growl." << endl; }

    /* A more sophisticated version would use pure virtual functions:
     *
     * virtual void say_something() = 0;
     */
};

class dog : public animal
{
public:
    void say_something() { cout << "Barf, barf..." << endl; }
};

class cat : public animal
{
public:
    void say_something() { cout << "Meow, meow..." << endl; }
};

int main()
{
    animal *a1 = new dog();
    animal *a2 = new cat();
    a1->say_something();
    a2->say_something();
}
Jaunitajaunt answered 11/2, 2010 at 2:31 Comment(0)
G
1

When coming from Java, one might find the concept of virtual vs. non virtual member functions confusing. The thing to remember is that Java methods correspond to virtual member functions in C++.

The question is not so much why we actually have virtual functions, but why do we have non-virtual ones? The way I justify them to myself (correct me if I'm wrong) is that they are cheaper to implement, as calls to them can be resolved at compile time.

Gaul answered 10/2, 2010 at 18:55 Comment(2)
Then again, there are final methods in Java that are not meant to be overriden.Replace
The reason the choice was made in C++ is because it takes work to design a class for inheritance, particularly since there is no root class (think Object in Java). If the designer hasn't explicitly decided to make a class inheritable, it shouldn't be inherited from.Kape
P
0

Virtual functions exist to help design the behavior of a base class. A base class of pure virtual functions cannot be instantiated and is called an abstract class.

It's up to the derived classes to implement those methods described by the virtual functions in the base class. Derived classes can then be instantiated (they exist and occupy memory).

Deriving from derived classes can redfine a function already defined in the parent object. This technique you already know as overriding and allows you to customize the behavior of this child object.

As you learn more C++, you'll find that inheritance isn't all that it's cracked up to be. Composition and is often a better alternative. Have fun.

Pathogenesis answered 10/2, 2010 at 18:5 Comment(0)
W
0

The classic example is that of a paint program where a base Shape class is created with a virtual draw() function. Then each of the shapes (circle, rectangle, triangle, etc) can be created as subclass that each implement their draw() function in the appropriate manner and the core paint program can keep a list of Shapes that will each do the appropriate draw() function even though only a pointer to the base Shape class is stored.

Waldman answered 10/2, 2010 at 23:21 Comment(0)
T
-1

The difference is just used when you call the method of the derived class, through a pointer to a base class object. In that moment you if the method you're calling was override in the derived class, you'll get the exceution of the base class, instead if was virtual then you got the execution of the derived class method.

#include <iostream>

class A{
    public:
    virtual void getA() { std::cout << "A in base" << std::endl;};
};

class B : public A {
    public:
    void getA() { std::cout << "A in derived class" << std::endl;}
};

int main(int argc, char** argv)
{
    A a;
    B b;
    a.getA();
    b.getA();

    A* t = new B;
    t->getA();
}

For example: in this program t->getA() print "A in derived class", but if there'were no virtual modificator in the base class A, then it would print "A in base".

Hope it helps.

Truancy answered 10/2, 2010 at 17:42 Comment(5)
The standard clearly defines both getA methods in your examples as overrides. A virtual method in the base class and all definitions of the same method in derived classes are overrides, and they define the basic brick for polymorphism. When a method is not virtual you cannot override it, you can hide it by defining the same method in a derived class, but those will not override the base class method.Replace
@Martin York: The answer wrongly identifies override with redefine. Only virtual functions can be overrides. The sentence: 'if the method you're calling was override in the derived class, you'll get the exceution of the base class' is associating the behavior of non-virtual not-overrides with the term override. When overrides are present the implementation will call the most derived override, not the base. I guess my other comment is not clear on why I had downvoted.Replace
@david you realize that your explanation is a wordplay. I'm thinking here very practical, you can called, being conceptual, as you want, the point keep being the same. It's just a very high C++ developer who could tell about the real difference between 'override' and 'hiding' as you said. And besides everything depends on C++ implementations of very strict languages concepts, So i don't think my answer could missguide someone. Course no one would try to explain so big and discussed concepts with so a simple example. Try to understand a bit the one who's asking.Truancy
the problem is that you got the 'override' part completely wrong. A virtual function in a derived class overrides the base method. The behavior you wrote in the above quoted line is not the behavior that overrides offer, but rather the behavior that non-overrides have. Since comments are too limited in space for a better explanation, I am following this discussion in the 'fake' answer here: #2239428Replace
Despite the stupid difference between words, this answer actually explain the applicable difference in a very understandable way.Curtsey
B
-1

Helicopters and airplanes both fly, but they do it in different ways -- they are both instances of some hypothetical object Flyer . You can ask the Flyer object to "fly" -- but Flyer is just a interface It doesn't know anything about flying other than that it should be able to fly.

However if both the helicopter and airplane follow the interface of flyer, than if had an airfield object and you gave it a Flyer all the airfield needs to do is to request the flyers to fly.

For example:

Airplace X=Airplane X("boeing 747");
Airfield::takeoff(&X);

Helicopter Y= Helicopter("Comache");
Airfield::takeof(&Y);

void Airfield::takeOff(Flyer * f)
{
     f->fly();
}

C++ is a strict type-safe language, and this sort of functionality (making function calls to derived classes indirectly via a base class) is only possible when RTTI is enabled for the object hierarchy, and qualifying a member function virtual enables this.

Burchfield answered 10/2, 2010 at 17:51 Comment(1)
@Hassan: RTTI in the sense most people mean when they think of C++ RTTI (i.e. the information required for the typeid operator and dynamic_cast) is not required for virtual method dispatch. Generally this requires only generation of one vtable per class and one vtable pointer per class instance. This is RTTI but not "RTTI" if you catch my drift. (Disclaimer: all above applies to most compilers but is in no way mandated by the ISO standard.)Cromer

© 2022 - 2024 — McMap. All rights reserved.