Let me show you the simple C++ code example first.
#include <iostream>
using namespace std;
class Person{
string m_name;
public:
virtual void saySomething(){
cout << "I am a person.";
}
};
class Student:public Person{
public:
void saySomething(){
cout << "I am a student." << endl;
}
};
class CSStudent:public Student{
public:
void saySomething(){
cout << "I am a CS Student." << endl;
}
};
int main(){
Person* p = new Person();
Student* s = new Student();
CSStudent* c = new CSStudent();
((Student*)c)->saySomething();
return 0;
}
In my example, Student is a derived class of Person.
Also, CSStudent is a derived class of Student.
I know virtual keyword make it possible to determine if it is derived class.
Question 1.
((Student*)c)->saySomething();
Why do I get "I am a CS Student."?
I expected "I am a Student." since I specify virtual keyword only for the Person.
Question 2.
I saw an example that puts a virtual keyword to only base case.
Also, I saw an example that puts virtual keywords to all base case and derived classes. What's the difference between these two?
Question 3.
virtual function is determined in run time.
What about non-virtual function? Is it determined in compile time?
For the first question, even if you cast c to another class based on the same base-class, it's still the original class (i.e. CSStudent). Virtual functions are (almost always) implemented through a jump table. So the c object have a table which contains the address to the actual function in the c object. This table will not change because you re-cast the type.
For the second question, there is no difference. If you mark a member function as virtual in the base class, it will be virtual in all child-classes as well. It's just that some people prefer to mark the functions in the child-classes virtual too. It can actually be good because then you don't have to check the base-class to see which functions are virtual and which are not.
And for the third question. Yes, virtual functions are calculated runtime using the table as described above, while non-virtual functions are determined at compilation time.
Question 1.
((Student*)c)->saySomething();
Why do I get "I am a CS Student."? I expected "I am a Student." since I specify virtual keyword only for the Person.
In C++, if the base class specifies that a function is virtual, then you don't need the virtual keyword in any derived classes for member functions with the same signature. You can include it if you want to (and it's generally good practice to do so), but it's optional.
Question 2.
I saw some example on the web page that mentions virtual keyword to only base case. Also, I saw some example that mentions virtual keyword to all base case and derived classes. What's the difference between these two?
As above: there is no difference. If the base class says a method with a particular signature is virtual, then that applies to all derived classes too.
Question 3.
virtual function is determined in run time. What about non-virtual function? Is it determined in compile time?
Yes. If your saySomething() function was non-virtual, then the calls would be resolved at compile-time, and the cast to Student* would mean you'd get the Student version of saySomething().
Why do I get "I am a CS Student."? I expected "I am a Student." since
I specify virtual keyword only for the Person.
In C++, if you specify the virtual keyword in a base class, that method will automatically be made virtual in any subclasses as well. (I won't try to speculate on why C++ works that way, but it does)
I saw an example that puts a virtual keyword to only base case. Also, I saw an example that puts virtual keywords to all base case and derived classes. What's the difference between these two?
Functionally there is no difference. I think stylistically the latter one is a little better in terms of being self-documenting.
virtual function is determined in run time. What about non-virtual
function? Is it determined in compile time?
Correct. In particular, the method implementation that gets called for a non-virtual method will be determined solely by the pointer type it was called through, rather than via dynamic lookup of the appropriate subclass method.
Related
In this code, I have defined three structs, base, derived and MoreDerived each inheriting from the previous member in the list.
However, I have defined the function f() to be virtual in the derived
struct, NOT in the base struct.
#include <iostream>
struct base {
void f() {
std::cout << "base\n";
}
};
struct derived : base {
virtual void f() {
std::cout << "derived\n";
}
};
struct morederived : derived {
void f() {
std::cout << "more derived\n";
}
};
int main()
{
derived d;
morederived md;
base* dp = &d;
base* mdp = &md;
dp->f();
mdp->f();
}
The code above prints base \n base as expected. And if I declare dp and mdp to be pointers of type derived*, the code prints derived \n more derived as expected again, since f is defined to be virtual in the derived.
Of course, this code is small and so the results are predictable. But in large code bases, is doing the above ever a good idea?
Note: I have not seen this in any codes yet, in my limited c++ experience, nor do I have any plans to use such a pattern (or anti-pattern :-D). I am asking this purely out of curiosity.
EDIT: I don't feel this question is not a duplicate to the one pointed out. I am not asking if the virtual keyword is necessary in a derived class. I am asking the effects/plusses/minuses of placing the virtual keyword on a function f() that has an implementation in the base class, but is declared virtual only in the derived class, and then is inherited by other classes.
Specifically I am asking if this thing is a patter or anti-pattern.
Yes, this breaks the Is-a contract. Your derived is not playing by the same rules as base.
This is never a good idea. You might want to consider composition for derived. I.e.
struct derived {
base b; // for whatever use you might have for base.
virtual void f() {
std::cout << "derived\n";
}
};
In my book, it qualifies as a code smell.
derived::f() actually hides base::f() rather than overriding it.
This means that base_ptr->f() always calls base::f(), even if base_ptr points at an instance of a derived class, whereas derived_ptr->f() will use virtual function dispatch.
The fact of making derived::f() virtual and documenting that it can be overridden, encourages implementers of classes like morederived to expect that a call of the form pointer->f(), if pointer points at an instance of morederived, to believe their version will be called. In reality, which version will be called depends on the type of pointer (e.g. different version called if it is base * or derived *).
That can result in quite an unpleasant surprise for anyone who uses the classes, and doesn't closely inspect all classes in the hierarchy. In large class hierarchies, particularly if provided by someone else, developers will not typically inspect a complete class hierarchy provided by someone else that closely. The will assume it works as advertised, if they care at all about their productivity.
If this sort of thing was present in a commercial class library, the vendor could expect to receive bug reports from customers bitten by such a bug, to lose customers of their library (on the premise that they introduced a bug through bad development technique), or both.
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.
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.
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.
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!!
You could say that you have to do it because that's one of the rules of the language.
There's a reason its helpful though.
When trying to validate the code that uses an Animal, the complier knows what functions exist on an Animal. Its possible to tell whether the code is correct without checking all classes that derive from animal. So that code doesn't need to depend on all those derived classes. If you derive a new class from Animal but forget to implement the makeNoise function that's an error in the new class not the code that uses the Animal base class and the complier can point you towards that error. Without the virtual function declared in Animal there would no way to tell if its the calling code or the new class that is in error.
A key point here is that these errors would be caught at compile-time for C++ because of its static typing. Other languages can allow dynamic typing, which can make some things easier but, the errors would only be spotted at runtime.
In Java, all functions are virtual by default. In C++ they are not, so when you call a non-virtual function on a pointer of a given type, that type's implementation of that function is invoked with the object's address as this.
class Animal {
public:
void sound() { std::cout << "splat\n"; }
virtual void appearance() { std::cout << "animaly\n"; }
};
class Cat {
public:
void sound() { std::cout << "meow\n"; }
virtual void appearance() { std::cout << "furry\n"; }
};
int main() {
Animal a;
Cat c;
Animal* ac = new Cat;
a.sound(); // splat
a.appearance(); // animaly
c.sound(); // meow
c.appearance(); // furry
ac->sound(); // splat
ac->appearance(); // furry
}
This would occur when you wanted to write a function that generalized on "Animal" rather than requiring a specific derived class pointer.
In java you use virtual methods too.
It improves the loosely coupling of your software.
For example, you can use a library and don't know which animal they use internally. There is a animal implementation you don't know and you can use it because it's an animal. You get the animal with a library.getAnimal method. Now you can use their animal without to know which noise it makes, because they have to implement the method makeNoise.
Edit: So to answer your question, c++ wants a explicit declaration and in java it is implicit. so yes it is a kind of language specific idiosyncracy.
This question already has answers here:
Virtual/pure virtual explained
(12 answers)
Closed 8 years ago.
With C++, virtual is used like this? What's the difference between the both?
class Animal
{
public:
virtual void something();
virtual void something() = 0;
}
I might be fuzzy on this but I think the first says: You can override me, and the second says, You must override me.
virtual void something() = 0; // says it is a pure virtual function
virtual void something(); // is a virtual function
And classes that contain atleast one pure virtual function are called abstract base classes.The main difference between an abstract base class and a regular polymorphic class is that because in abstract base classes at least one of its members lacks implementation, we cannot create instances (objects) of it.
The first states that the function is virtual: that subclasses can override the behaviour. However, the function still has an implementation in the base class. The second is pure virtual: it doesn't have an implementation, and must be overridden by a subclass. It's similar to the abstract keyword in Java and C#. It makes the class abstract too, so it cannot be instantiated.
The second "something" must be implemented by subclasses and any class containing "xxx() = 0" cannot be directly instantiated. It's called a "pure virtual" function and classes containing them are "abstract". A class containing nothing but pure virtuals is "pure abstract".
first one is just declaring a virtual method. if you extend the class and override that method then the child class' implementation is called.
2nd one is a pure virtual method. in other words neither your class or any class that extends it be instantiated (abstract) without first providing a definition for something().
Consider:
class Sloth : public Animal { void something() { ... } };
Animal animal;
Sloth sloth;
Here, we're trying to create two objects - an Animal and a Sloth. But, should we be allowed to create an animal? Perhaps the programmer has created Animal just so it can be used to refer polymorphically to derived types, as in:
std::vector<Animal*> zoo;
zoo.push_back(new Sloth());
zoo.push_back(new Sea_Eagle());
They might then expect p_animal->something() to do something useful. Given Animal is only inteded for this polymorphic abstraction, it would be wrong for anyone to put an actual "new Animal()" object directly into the zoo (or operate on one anywhere else in the program).
Say it was possible - what should then happen if a programmer using this Animal class creates an instance and calls the something() function? Perhaps nothing, or perhaps it's an error condition and should never appear in good code - rather than having Animal's something() function print an error message or throws an exception at run time. That's ugly - run-time errors mean the program is failing when the client's trying to use it.
C++ supports the "= 0" notation so that the compiler knows to prevent (base-class) Animal objects being created at compile time, so you can ship software that always works for the user.
I understand the need for a virtual destructor. But why do we need a pure virtual destructor? In one of the C++ articles, the author has mentioned that we use pure virtual destructor when we want to make a class abstract.
But we can make a class abstract by making any of the member functions as pure virtual.
So my questions are
When do we really make a destructor pure virtual? Can anybody give a good real time example?
When we are creating abstract classes is it a good practice to make the destructor also pure virtual? If yes..then why?
Probably the real reason that pure virtual destructors are allowed is that to prohibit them would mean adding another rule to the language and there's no need for this rule since no ill-effects can come from allowing a pure virtual destructor.
Nope, plain old virtual is enough.
If you create an object with default implementations for its virtual methods and want to make it abstract without forcing anyone to override any specific method, you can make the destructor pure virtual. I don't see much point in it but it's possible.
Note that since the compiler will generate an implicit destructor for derived classes, if the class's author does not do so, any derived classes will not be abstract. Therefore having the pure virtual destructor in the base class will not make any difference for the derived classes. It will only make the base class abstract (thanks for #kappa's comment).
One may also assume that every deriving class would probably need to have specific clean-up code and use the pure virtual destructor as a reminder to write one but this seems contrived (and unenforced).
Note: The destructor is the only method that even if it is pure virtual has to have an implementation in order to instantiate derived classes (yes pure virtual functions can have implementations, being pure virtual means derived classes must override this method, this is orthogonal to having an implementation).
struct foo {
virtual void bar() = 0;
};
void foo::bar() { /* default implementation */ }
class foof : public foo {
void bar() { foo::bar(); } // have to explicitly call default implementation.
};
All you need for an abstract class is at least one pure virtual function. Any function will do; but as it happens, the destructor is something that any class will have—so it's always there as a candidate. Furthermore, making the destructor pure virtual (as opposed to just virtual) has no behavioral side effects other than to make the class abstract. As such, a lot of style guides recommend that the pure virtual destuctor be used consistently to indicate that a class is abstract—if for no other reason than it provides a consistent place someone reading the code can look to see if the class is abstract.
If you want to create an abstract base class:
that can't be instantiated (yep, this is redundant with the term "abstract"!)
but needs virtual destructor behavior (you intend to carry around pointers to the ABC rather than pointers to the derived types, and delete through them)
but does not need any other virtual dispatch behavior for other methods (maybe there are no other methods? consider a simple protected "resource" container that needs a constructors/destructor/assignment but not much else)
...it's easiest to make the class abstract by making the destructor pure virtual and providing a definition (method body) for it.
For our hypothetical ABC:
You guarantee that it cannot be instantiated (even internal to the class itself, this is why private constructors may not be enough), you get the virtual behavior you want for the destructor, and you do not have to find and tag another method that doesn't need virtual dispatch as "virtual".
Here I want to tell when we need virtual destructor and when we need pure virtual destructor
class Base
{
public:
Base();
virtual ~Base() = 0; // Pure virtual, now no one can create the Base Object directly
};
Base::Base() { cout << "Base Constructor" << endl; }
Base::~Base() { cout << "Base Destructor" << endl; }
class Derived : public Base
{
public:
Derived();
~Derived();
};
Derived::Derived() { cout << "Derived Constructor" << endl; }
Derived::~Derived() { cout << "Derived Destructor" << endl; }
int _tmain(int argc, _TCHAR* argv[])
{
Base* pBase = new Derived();
delete pBase;
Base* pBase2 = new Base(); // Error 1 error C2259: 'Base' : cannot instantiate abstract class
}
When you want that no one should be able to create the object of Base class directly, use pure virtual destructor virtual ~Base() = 0. Usually at-least one pure virtual function is required, let's take virtual ~Base() = 0, as this function.
When you do not need above thing, only you need the safe destruction of Derived class object
Base* pBase = new Derived();
delete pBase;
pure virtual destructor is not required, only virtual destructor will do the job.
From the answers I have read to your question, I couldn't deduce a good reason to actually use a pure virtual destructor. For example, the following reason doesn't convince me at all:
Probably the real reason that pure virtual destructors are allowed is that to prohibit them would mean adding another rule to the language and there's no need for this rule since no ill-effects can come from allowing a pure virtual destructor.
In my opinion, pure virtual destructors can be useful. For example, assume you have two classes myClassA and myClassB in your code, and that myClassB inherits from myClassA. For the reasons mentioned by Scott Meyers in his book "More Effective C++", Item 33 "Making non-leaf classes abstract", it is better practice to actually create an abstract class myAbstractClass from which myClassA and myClassB inherit. This provides better abstraction and prevents some problems arising with, for example, object copies.
In the abstraction process (of creating class myAbstractClass), it can be that no method of myClassA or myClassB is a good candidate for being a pure virtual method (which is a prerequisite for myAbstractClass to be abstract). In this case, you define the abstract class's destructor pure virtual.
Hereafter a concrete example from some code I have myself written. I have two classes, Numerics/PhysicsParams which share common properties. I therefore let them inherit from the abstract class IParams. In this case, I had absolutely no method at hand that could be purely virtual. The setParameter method, for example, must have the same body for every subclass. The only choice that I have had was to make IParams' destructor pure virtual.
struct IParams
{
IParams(const ModelConfiguration& aModelConf);
virtual ~IParams() = 0;
void setParameter(const N_Configuration::Parameter& aParam);
std::map<std::string, std::string> m_Parameters;
};
struct NumericsParams : IParams
{
NumericsParams(const ModelConfiguration& aNumericsConf);
virtual ~NumericsParams();
double dt() const;
double ti() const;
double tf() const;
};
struct PhysicsParams : IParams
{
PhysicsParams(const N_Configuration::ModelConfiguration& aPhysicsConf);
virtual ~PhysicsParams();
double g() const;
double rho_i() const;
double rho_w() const;
};
If you want to stop instantiating of base class without making any change in your already implemented and tested derive class, you implement a pure virtual destructor in your base class.
You are getting into hypotheticals with these answers, so I will try to make a simpler, more down to earth explanation for clarity's sake.
The basic relationships of object oriented design are two:
IS-A and HAS-A. I did not make those up. That is what they are called.
IS-A indicates that a particular object identifies as being of the class that is above it in a class hierarchy. A banana object is a fruit object if it is a subclass of the fruit class. This means that anywhere a fruit class can be used, a banana can be used. It is not reflexive , though. You can not substitute a base class for a specific class if that specific class is called for.
Has-a indicated that an object is part of a composite class and that there is an ownership relationship. It means in C++ that it is a member object and as such the onus is on the owning class to dispose of it or hand ownership off before destructing itself.
These two concepts are easier to realize in single-inheritance languages than in a multiple inheritance model like c++, but the rules are essentially the same. The complication comes when the class identity is ambiguous, such as passing a Banana class pointer into a function that takes a Fruit class pointer.
Virtual functions are, firstly, a run-time thing. It is part of polymorphism in that it is used to decide which function to run at the time it is called in the running program.
The virtual keyword is a compiler directive to bind functions in a certain order if there is ambiguity about the class identity. Virtual functions are always in parent classes (as far as I know) and indicate to the compiler that binding of member functions to their names should take place with the subclass function first and the parent class function after.
A Fruit class could have a virtual function color() that returns "NONE" by default.
The Banana class color() function returns "YELLOW" or "BROWN".
But if the function taking a Fruit pointer calls color() on the Banana class sent to it -- which color() function gets invoked?
The function would normally call Fruit::color() for a Fruit object.
That would 99% of the time not be what was intended.
But if Fruit::color() was declared virtual then Banana:color() would be called for the object because the correct color() function would be bound to the Fruit pointer at the time of the call.
The runtime will check what object the pointer points to because it was marked virtual in the Fruit class definition.
This is different than overriding a function in a subclass. In that case
the Fruit pointer will call Fruit::color() if all it knows is that it IS-A pointer to Fruit.
So now to the idea of a "pure virtual function" comes up.
It is a rather unfortunate phrase as purity has nothing to do with it. It means that it is intended that the base class method is never to be called.
Indeed a pure virtual function can not be called. It must still be defined, however. A function signature must exist. Many coders make an empty implementation {} for completeness, but the compiler will generate one internally if not. In that case when the function is called even if the pointer is to Fruit , Banana::color() will be called as it is the only implementation of color() there is.
Now the final piece of the puzzle: constructors and destructors.
Pure virtual constructors are illegal, completely. That is just out.
But pure virtual destructors do work in the case that you want to forbid the creation of a base class instance. Only sub classes can be instantiated if the destructor of the base class is pure virtual.
the convention is to assign it to 0.
virtual ~Fruit() = 0; // pure virtual
Fruit::~Fruit(){} // destructor implementation
You do have to create an implementation in this case. The compiler knows this is what you are doing and makes sure you do it right, or it complains mightily that it can not link to all the functions it needs to compile. The errors can be confusing if you are not on the right track as to how you are modeling your class hierarchy.
So you are forbidden in this case to create instances of Fruit, but allowed to create instances of Banana.
A call to delete of the Fruit pointer that points to an instance of Banana
will call Banana::~Banana() first and then call Fuit::~Fruit(), always.
Because no matter what, when you call a subclass destructor, the base class destructor must follow.
Is it a bad model? It is more complicated in the design phase, yes, but it can ensure that correct linking is performed at run-time and that a subclass function is performed where there is ambiguity as to exactly which subclass is being accessed.
If you write C++ so that you only pass around exact class pointers with no generic nor ambiguous pointers, then virtual functions are not really needed.
But if you require run-time flexibility of types (as in Apple Banana Orange ==> Fruit ) functions become easier and more versatile with less redundant code.
You no longer have to write a function for each type of fruit, and you know that every fruit will respond to color() with its own correct function.
I hope this long-winded explanation solidifies the concept rather than confuses things. There are a lot of good examples out there to look at,
and look at enough and actually run them and mess with them and you will get it.
You asked for an example, and I believe the following provides a reason for a pure virtual destructor. I look forward to replies as to whether this is a good reason...
I do not want anyone to be able to throw the error_base type, but the exception types error_oh_shucks and error_oh_blast have identical functionality and I don't want to write it twice. The pImpl complexity is necessary to avoid exposing std::string to my clients, and the use of std::auto_ptr necessitates the copy constructor.
The public header contains the exception specifications that will be available to the client to distinguish different types of exception being thrown by my library:
// error.h
#include <exception>
#include <memory>
class exception_string;
class error_base : public std::exception {
public:
error_base(const char* error_message);
error_base(const error_base& other);
virtual ~error_base() = 0; // Not directly usable
virtual const char* what() const;
private:
std::auto_ptr<exception_string> error_message_;
};
template<class error_type>
class error : public error_base {
public:
error(const char* error_message) : error_base(error_message) {}
error(const error& other) : error_base(other) {}
~error() {}
};
// Neither should these classes be usable
class error_oh_shucks { virtual ~error_oh_shucks() = 0; }
class error_oh_blast { virtual ~error_oh_blast() = 0; }
And here is the shared implementation:
// error.cpp
#include "error.h"
#include "exception_string.h"
error_base::error_base(const char* error_message)
: error_message_(new exception_string(error_message)) {}
error_base::error_base(const error_base& other)
: error_message_(new exception_string(other.error_message_->get())) {}
error_base::~error_base() {}
const char* error_base::what() const {
return error_message_->get();
}
The exception_string class, kept private, hides std::string from my public interface:
// exception_string.h
#include <string>
class exception_string {
public:
exception_string(const char* message) : message_(message) {}
const char* get() const { return message_.c_str(); }
private:
std::string message_;
};
My code then throws an error as:
#include "error.h"
throw error<error_oh_shucks>("That didn't work");
The use of a template for error is a little gratuitous. It saves a bit of code at the expense of requiring clients to catch errors as:
// client.cpp
#include <error.h>
try {
} catch (const error<error_oh_shucks>&) {
} catch (const error<error_oh_blast>&) {
}
Maybe there is another REAL USE-CASE of pure virtual destructor which I actually can't see in other answers :)
At first, I completely agree with marked answer: It is because forbidding pure virtual destructor would need an extra rule in language specification. But it's still not the use case that Mark is calling for :)
First imagine this:
class Printable {
virtual void print() const = 0;
// virtual destructor should be here, but not to confuse with another problem
};
and something like:
class Printer {
void queDocument(unique_ptr<Printable> doc);
void printAll();
};
Simply - we have interface Printable and some "container" holding anything with this interface. I think here it is quite clear why print() method is pure virtual. It could have some body but in case there is no default implementation, pure virtual is an ideal "implementation" (="must be provided by a descendant class").
And now imagine exactly the same except it is not for printing but for destruction:
class Destroyable {
virtual ~Destroyable() = 0;
};
And also there could be a similar container:
class PostponedDestructor {
// Queues an object to be destroyed later.
void queObjectForDestruction(unique_ptr<Destroyable> obj);
// Destroys all already queued objects.
void destroyAll();
};
It's simplified use-case from my real application. The only difference here is that "special" method (destructor) was used instead of "normal" print(). But the reason why it is pure virtual is still the same - there is no default code for the method.
A bit confusing could be the fact that there MUST be some destructor effectively and compiler actually generates an empty code for it. But from the perspective of a programmer pure virtuality still means: "I don't have any default code, it must be provided by derived classes."
I think it's no any big idea here, just more explanation that pure virtuality works really uniformly - also for destructors.
This is a decade old topic :)
Read last 5 paragraphs of Item #7 on "Effective C++" book for details, starts from "Occasionally it can be convenient to give a class a pure virtual destructor...."
we need to make destructor virtual bacause of the fact that , if we dont make the destructor virtual then compiler will only destruct the contents of base class , n all the derived classes will remain un changed , bacuse compiler will not call the destructor of any other class except the base class.
When exactly does the compiler create a virtual function table?
1) when the class contains at least one virtual function.
OR
2) when the immediate base class contains at least one virtual function.
OR
3) when any parent class at any level of the hierarchy contains at least one virtual function.
A related question to this:
Is it possible to give up dynamic dispatch in a C++ hierarchy?
e.g. consider the following example.
#include <iostream>
using namespace std;
class A {
public:
virtual void f();
};
class B: public A {
public:
void f();
};
class C: public B {
public:
void f();
};
Which classes will contain a V-Table?
Since B does not declare f() as virtual, does class C get dynamic polymorphism?
Beyond "vtables are implementation-specific" (which they are), if a vtable is used: there will be unique vtables for each of your classes. Even though B::f and C::f are not declared virtual, because there is a matching signature on a virtual method from a base class (A in your code), B::f and C::f are both implicitly virtual. Because each class has at least one unique virtual method (B::f overrides A::f for B instances and C::f similarly for C instances), you need three vtables.
You generally shouldn't worry about such details. What matters is whether you have virtual dispatch or not. You don't have to use virtual dispatch, by explicitly specifying which function to call, but this is generally only useful when implementing a virtual method (such as to call the base's method). Example:
struct B {
virtual void f() {}
virtual void g() {}
};
struct D : B {
virtual void f() { // would be implicitly virtual even if not declared virtual
B::f();
// do D-specific stuff
}
virtual void g() {}
};
int main() {
{
B b; b.g(); b.B::g(); // both call B::g
}
{
D d;
B& b = d;
b.g(); // calls D::g
b.B::g(); // calls B::g
b.D::g(); // not allowed
d.D::g(); // calls D::g
void (B::*p)() = &B::g;
(b.*p)(); // calls D::g
// calls through a function pointer always use virtual dispatch
// (if the pointed-to function is virtual)
}
return 0;
}
Some concrete rules that may help; but don't quote me on these, I've likely missed some edge cases:
If a class has virtual methods or virtual bases, even if inherited, then instances must have a vtable pointer.
If a class declares non-inherited virtual methods (such as when it doesn't have a base class), then it must have its own vtable.
If a class has a different set of overriding methods than its first base class, then it must have its own vtable, and cannot reuse the base's. (Destructors commonly require this.)
If a class has multiple base classes, with the second or later base having virtual methods:
If no earlier bases have virtual methods and the Empty Base Optimization was applied to all earlier bases, then treat this base as the first base class.
Otherwise, the class must have its own vtable.
If a class has any virtual base classes, it must have its own vtable.
Remember that a vtable is similar to a static data member of a class, and instances have only pointers to these.
Also see the comprehensive article C++: Under the Hood (March 1994) by Jan Gray. (Try Google if that link dies.)
Example of reusing a vtable:
struct B {
virtual void f();
};
struct D : B {
// does not override B::f
// does not have other virtuals of its own
void g(); // still might have its own non-virtuals
int n; // and data members
};
In particular, notice B's dtor isn't virtual (and this is likely a mistake in real code), but in this example, D instances will point to the same vtable as B instances.
The answer is, 'it depends'. It depends on what you mean by 'contain a vtbl' and it depends on the decisions made by the implementor of the particular compiler.
Strictly speaking, no 'class' ever contains a virtual function table. Some instances of some classes contain pointers to virtual function tables. However, that's just one possible implementation of the semantics.
In the extreme, a compiler could hypothetically put a unique number into the instance that indexed into a data structure used for selecting the appropriate virtual function instance.
If you ask, 'What does GCC do?' or 'What does Visual C++ do?' then you could get a concrete answer.
#Hassan Syed's answer is probably closer to what you were asking about, but it is really important to keep the concepts straight here.
There is behavior (dynamic dispatch based on what class was new'ed) and there's implementation. Your question used implementation terminology, though I suspect you were looking for a behavioral answer.
The behavioral answer is this: any class that declares or inherits a virtual function will exhibit dynamic behavior on calls to that function. Any class that does not, will not.
Implementation-wise, the compiler is allowed to do whatever it wants to accomplish that result.
Answer
a vtable is created when a class declaration contains a virtual function. A vtable is introduced when a parent -- anywhere in the heirarchy -- has a virtual function, lets call this parent Y. Any parent of Y WILL NOT have a vtable (unless they have a virtual for some other function in their heirarchy).
Read on for discussion and tests
-- explanation --
When you specify a member function as virtual, there is a chance that you may try to use sub-classes via a base-class polymorphically at run-time. To maintain c++'s guarantee of performance over language design they offered the lightest possible implementation strategy -- i.e., one level of indirection, and only when a class might be used polymorphically at runtime, and the programmer specifies this by setting at least one function to be virtual.
You do not incur the cost of the vtable if you avoid the virtual keyword.
-- edit : to reflect your edit --
Only when a base class contains a virtual function do any other sub-classes contain a vtable. The parents of said base class do not have a vtable.
In your example all three classes will have a vtable, this is because you can try to use all three classes via an A*.
--test - GCC 4+ --
#include <iostream>
class test_base
{
public:
void x(){std::cout << "test_base" << "\n"; };
};
class test_sub : public test_base
{
public:
virtual void x(){std::cout << "test_sub" << "\n"; } ;
};
class test_subby : public test_sub
{
public:
void x() { std::cout << "test_subby" << "\n"; }
};
int main()
{
test_sub sub;
test_base base;
test_subby subby;
test_sub * psub;
test_base *pbase;
test_subby * psubby;
pbase = ⊂
pbase->x();
psub = &subby;
psub->x();
return 0;
}
output
test_base
test_subby
test_base does not have a virtual table therefore anything casted to it will use the x() from test_base. test_sub on the other hand changes the nature of x() and its pointer will indirect through a vtable, and this is shown by test_subby's x() being executed.
So, a vtable is only introduced in the hierarchy when the keyword virtual is used. Older ancestors do not have a vtable, and if a downcast occurs it will be hardwired to the ancestors functions.
You made an effort to make your question very clear and precise, but there's still a bit of information missing. You probably know, that in implementations that use V-Table, the table itself is normally an independent data structure, stored outside the polymorphic objects, while objects themselves only store a implicit pointer to the table. So, what is it you are asking about? Could be:
When does an object get an implicit pointer to V-Table inserted into it?
or
When is a dedicated, individual V-Table created for a given type in the hierarchy?
The answer to the first question is: an object gets an implicit pointer to V-Table inserted into it when the object is of polymorphic class type. The class type is polymorphic if it contains at least one virtual function, or any of its direct or indirect parents are polymorphic (this is answer 3 from your set). Note also, that in case of multiple inheritance, an object might (and will) end up containing multiple V-Table pointers embedded into it.
The answer to the second question could be the same as to the first (option 3), with a possible exception. If some polymorphic class in single inheritance hierarchy has no virtual functions of its own (no new virtual functions, no overrides for parent virtual function), it is possible that implementation might decide not to create an individual V-Table for this class, but instead use it's immediate parent's V-Table for this class as well (since it is going to be the same anyway). I.e. in this case both objects of parent type and objects of derived type will store the same value in their embedded V-Table pointers. This is, of course, highly dependent on implementation. I checked GCC and MS VS 2005 and they don't act that way. They both do create an individual V-Table for the derived class in this situation, but I seem to recall hearing about implementations that don't.
C++ standards doesn't mandate using V-Tables to create the illusion of polymorphic classes. Most of the time implementations use V-Tables, to store the extra information needed. In short, these extra pieces of information are equipped when you have at least one virtual function.
The behavior is defined in chapter 10.3, paragraph 2 of the C++ language specification:
If a virtual member function vf is
declared in a class Base and in a
class Derived, derived directly or
indirectly from Base, a member
function vf with the same name and
same parameter list as Base::vf is
declared, then Derived::vf is also
virtual ( whether or not it is so
declared ) and it overrides Base::vf.
A italicized the relevant phrase. Thus, if your compiler creates v-tables in the usual sense then all classes will have a v-table since all their f() methods are virtual.