C++/Glad to see you here again!
Expert: Ralph McArdell - 4/8/2005
QuestionHi Ralph,
How are you doing?
May I ask you answer the following two questions?
1/ Is there virtual class, pure virtual class or abstract class?
2/ If any, what is its meanings?
Thanks,
lzzzz
AnswerI have been busy with some work on and off over the last year or so which involves me being away during the week - which is why I have only been on question answering at the weekends for much of this time.
Oh go on ask away then...
1/ There are virtual classes and abstract classes - both of which are used as base classes - virtual base class and abstract base class. There is no such thing as far as I am aware as a pure virtual class or base class. This is because virtual when applied to a class is different to the case when applied to a member function.
2/ OK let's start with abstract base classes (or ABCs). An abstract base class is any class that declares at least one pure virtual member function - and thus cannot be instantiated because there are undefined virtual function slots in the vtable - hence the class is abstract. The only way to create objects having such a type is to define a sub-class (or more than one sub-class) which provides definitions for all virtual member functions - hence such classes have to be used as base classes. The compiler will generally issue an error if you do try to create an instance of an ABC.
Now a virtual base class is a class that when used as a base class is declared to be virtual:
class SC : public virtual VBC
{
// ...
};
So unlike an ABC there is nothing about the definition of a class used as a virtual base class, such as VBC in my example, that the compiler can check and issue an error if not used as a virtual base class.
The use of virtual base classes is only necessary in certain class hierarchies involving diamond shaped multiple inheritance graphs (use a fixed spaced font to view some of the next examples, otherwise they will be meaningless as well as cruddy!):
BaseClass
^ ^
| |
SC1_a SC1_b
^ ^
| |
LeafClass
Here LeafClass inherits from SC1_a and SC1_b - both of which inherit from BaseClass. So how many BaseClass sub-objects does a LeafClass object contain? How many should it contain?
The answer to the first question depends on how BaseClass is inherited from and the answer to the second is that it depends on your design and requirements.
If you derive from BaseClass normally - i.e. non-virtually - then you get two BaseClass sub-objects in a LeafClass - one as a sub-object of the SC1_a LeafClass sub-object and one as a sub-object of the SC1_b sub-object:
BaseClass BaseClass
^ ^
| |
SC1_a SC1_b
^ ^
| |
LeafClass
Which in (very brief, outline) C++ would look something like so:
class BaseClass {};
class SC1_a : public BaseClass {};
class SC1_b : public BaseClass {};
class LeafClass : public SC1_a, public SC1_b {};
However if you have SC1_a and SC1_b derive virtually from BaseClass then LeafClass only gets _one_ BaseClass sub-object:
BaseClass
^ ^
| |
SC1_a SC1_b
^ ^
| |
LeafClass
Which in brief outline C++ would look like so:
class BaseClass {};
class SC1_a : public virtual BaseClass {};
class SC1_b : public virtual BaseClass {};
class LeafClass : public SC1_a, public SC1_b {};
I think the reason virtual base classes are virtual are firstly virtual was a convenient existing keyword - C++ people hate adding keywords to the language and secondly that the sub-objects of classes with virtual bases are in fact virtual if the type is derived from.
This is because (as I understand it) that virtual base class sub-objects are generally part of objects of the most derived type in a hierarchy - so are only part of an object of the class specifying them as virtual bases if the object is of that type. In my example if we created an SC1_a object having a BaseClass as a virtual base class then the BaseClass sub-object is part of the SC1_a object. However in a LeafClass object the BaseClass virtual base of the SC1_a and SC1_b sub-objects is virtual to these sub-objects and is in fact a direct sub-object of the LeafClass object.
To make this clearer let's show how objects are composed by showing base class sub-objects as members of the classes they are bases for.
So for my non-virtual base class example we have the following setup for a LeafClass:
class BaseClass {};
class SC1_a : public BaseClass
{
BaseClass base1;
};
class SC1_b : public BaseClass
{
BaseClass base1;
};
class LeafClass : public SC1_a, public SC1_b
{
SC1_a base1;
SC1_b base2;
};
Now in the virtual base class example in which BaseClass is a virtual base of both SC1_a and SC1_b we have for a LeafClass object:
class BaseClass {};
class SC1_a : public virtual BaseClass
{
};
class SC1_b : public virtual BaseClass
{
};
class LeafClass : public SC1_a, public SC1_b
{
SC1_a base1;
SC1_b base2;
BaseClass base3;
};
However if we ask for an SC1_a object then this is the most derived type and so it has the virtual BaseClass sub-object:
class SC1_a a : public virtual BaseClass
{
BaseClass base1;
};
I think you will find that the layout of the bases and members varies from compiler to compiler where it is not tied down by the standard.
If you think this is all very complex you are correct - I am so glad I am not a C++ compiler writer! It is probably why many languages that support object oriented programming steer away from multiple inheritance of implementation (types having data and/or function definitions) is involved. This is true of both Java and .NET - both only allow multiple inheritance from interfaces (types defining only pure virtual functions). You can inherit from only one class in such languages / systems.