Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trouble understanding C++ `virtual`

I'm having trouble understanding what the purpose of the virtual keyword in C++. I know C and Java very well but I'm new to C++

From wikipedia

In object-oriented programming, a virtual function or virtual method is a function or method whose behavior can be overridden within an inheriting class by a function with the same signature.

However I can override a method as seen below without using the virtual keyword

#include <iostream>

using namespace std;

class A {
    public:
        int a();
};

int A::a() {
    return 1;   
}

class B : A { 
    public:
        int a();
};

int B::a() {
    return 2;
}

int main() {
    B b;
    cout << b.a() << endl;
    return 0;
}

//output: 2

As you can see below, the function A::a is successfully overridden with B::a without requiring virtual

Compounding my confusion is this statement about virtual destructors, also from wikipedia

as illustrated in the following example, it is important for a C++ base class to have a virtual destructor to ensure that the destructor from the most derived class will always be called.

So virtual also tells the compiler to call up the parent's destructors? This seems to be very different from my original understanding of virtual as "make the function overridable"

like image 509
Mike Avatar asked Dec 01 '09 21:12

Mike


2 Answers

Make the following changes and you will see why:

#include <iostream>

using namespace std;

class A {
    public:
        int a();
};

int A::a() {
    return 1;   
}

class B : public A { // Notice public added here
    public:
        int a();
};

int B::a() {
    return 2;
}

int main() {
    A* b = new B(); // Notice we are using a base class pointer here
    cout << b->a() << endl; // This will print 1 instead of 2
    delete b; // Added delete to free b
    return 0;
}

Now, to make it work like you intended:

#include <iostream>

using namespace std;

class A {
    public:
        virtual int a(); // Notice virtual added here
};

int A::a() {
    return 1;   
}

class B : public A { // Notice public added here
    public:
        virtual int a(); // Notice virtual added here, but not necessary in C++
};

int B::a() {
    return 2;
}

int main() {
    A* b = new B(); // Notice we are using a base class pointer here
    cout << b->a() << endl; // This will print 2 as intended
    delete b; // Added delete to free b
    return 0;
}

The note that you've included about virtual destructors is exactly right. In your sample there is nothing that needs to be cleaned-up, but say that both A and B had destructors. If they aren't marked virtual, which one is going to get called with the base class pointer? Hint: It will work exactly the same as the a() method did when it was not marked virtual.

like image 94
ConsultUtah Avatar answered Oct 14 '22 14:10

ConsultUtah


You could think of it as follows.

All functions in Java are virtual. If you have a class with a function, and you override that function in a derived class, it will be called, no matter the declared type of the variable you use to call it.

In C++, on the other hand, it won't necessarily be called.

If you have a base class Base and a derived class Derived, and they both have a non-virtual function in them named 'foo', then

Base * base;
Derived *derived;

base->foo(); // calls Base::foo
derived->foo(); // calls Derived::foo

If foo is virtual, then both call Derived::foo.

like image 36
bmargulies Avatar answered Oct 14 '22 13:10

bmargulies