Reputation: 34615
I figured out 2 different situations where virtual
is used.
If a baseClass
has a function defined virtual
, then the derivedClass
is going to override the function.
The baseClass::~baseClass()
should be defined virtual
, if there is any class derived from it. Here it means, the derived class destruction first takes place followed by base class destruction.
Are there any other situations where virtual
is used ?
Upvotes: 0
Views: 216
Reputation: 1581
The virtual
keyword gives the function late binding. In late binding the function call is not bound to anything until run time. In polymorphism and at run time the class looks up its v-table to decide what overloaded function to call. The destructor is often virtual
when its class is polymorphic. virtual
is probably the most opposite to inline
, and very similar (at least in my opinion) to extern
.
Upvotes: 0
Reputation: 2777
there is actually one more little quirk with virtual. let's say you have a class which you would like to be what for example java, c#, php and actionscript would call abstract, but this class has no pure virtual methods. then you can declare the destructor as a pure virtual method in the class declaration, but still implement it. here's an example:
#include <iostream>
class MyAbstractClass
{
public:
MyAbstractClass(int i);
virtual ~MyAbstractClass() = 0;
int getI() const;
private:
int m_i;
};
class MyConcreteClass : public MyAbstractClass
{
public:
MyConcreteClass(int i);
~MyConcreteClass();
};
MyAbstractClass::MyAbstractClass(int i) :
m_i(i)
{
std::cout << "constructor of MyAbstractClass\n";
}
MyAbstractClass::~MyAbstractClass()
{
std::cout << "destructor of MyAbstractClass\n";
}
int MyAbstractClass::getI() const
{
return m_i;
}
MyConcreteClass::MyConcreteClass(int i) :
MyAbstractClass(i)
{
std::cout << "constructor of MyConcreteClass\n";
}
MyConcreteClass::~MyConcreteClass()
{
std::cout << "destructor of MyConcreteClass\n";
}
int main(int argc, char* argv[])
{
MyConcreteClass a(5);
std::cout << a.getI();
std::cout << std::endl;
MyAbstractClass b(5); //compile error, can't instantiate a class with abstract functions
return 0;
}
Upvotes: 0
Reputation: 354979
virtual
always has the same meaning when applied to a member function. When a member function is virtual
, it means that calls to that member function will be dispatched dynamically.
That is, the function to be called will be selected based on the dynamic type (the actual type), not the static type. Based on the actual type of the object, the final overrider of the virtual function will be called.
The only reason that destructors are "different" is that a derived class destructor has a different name than the base class destructor. The behavior of the derived class destructor is not affected by it being declared virtual
, though: a derived class destructor always calls base class destructors after it has run.
As an example of the behavior of virtual
functions:
struct B {
void f() { }
virtual void g() { }
};
struct D : B {
void f() { }
virtual void g() { }
};
int main() {
B* p = new D();
}
The dynamic type of the expression *p
is D
because the actual type of the object pointed to by p
is a D
. You used new D()
to create it, so it's dynamic type is D
.
The static type of the expression *p
is B
because that is the type named in the code. Without running the program or evaluating what got assigned to p
, the compiler doesn't know the most derived type of the object given by *p
; it just knows that whatever it is, it is a B
or something derived from B
.
If you call p->f()
, the call is dispatched statically because B::f
is not virtual
. The compiler looks at the static type of *p
and selects the function to be called based on that (B::f
).
If you call p->g()
, the call is dispatched dynamically because B::g
is virtual
. At runtime, the dynamic type of the object is checked (using a vtable in many common implementations), and the final overrider is called. In this case, the final overrider is D::g
because D
is the most derived class that overrides B::g
(if there was another class derived from D
, it could opt to override B::g
as well).
Upvotes: 1
Reputation: 361252
Example of virtual inheritance,
class UltimateBase{};
class Base1 : public virtual UltimateBase{};
class Base2 : public virtual UltimateBase {};
class Derived : public Base1, public Base2{};
So that instances of Derived
class may have only one subobject of UltimateBase
class.
Upvotes: 0
Reputation: 8317
virtual inheritance is a big one. among other things it resolves issues with duplicate members introduced by multiple inheritance. google "dreaded diamond pattern" for the full details there.
Upvotes: 0
Reputation: 62053
There's also virtual inheritance, where the base class is referenced by an indirection.
In C++, what is a virtual base class?
Upvotes: 1