Pure Virtual functions

Started by
29 comments, last by SiCrane 18 years, 6 months ago
C++ is a language rich in features. There are many different styles of programming, each needing certain features. So don't be surprised if you don't see the use of a particular feature. There are other people out there who can't live without it. Eventually you will learn how to integrate the features into your programs naturally, without it seeming forced. Often the best programs are the ones that seem the most natural to write. Don't try to fit square pegs into round holes and so on.
Advertisement
Quote:Original post by Mantear
In other words, my question is: Why use a pure virtual instead of providing some default behavior?

You can do both, if the situation warrants it. I've never seen where you would want to, but the option is there. I believe the C++ FAQ Lite has a section on it.

CM
Quote:Original post by DigiDude
I, too, am not completely sure why you would use them. I think that, maybe, it's like constant functions. (example) You don't have to make your functions constannt but it provides some protection from changing data and it makes your intentions clearer to other people. When you use pure virtual functions you are telling other people that you will be deriving other classes from that class.

(I did not just make any relation between pure virutal functions and constant functions)


Whenever you have a virtual function, you are telling other people that you intend classes to derive from the base class. Making a function pure virtual doesn't give greater indication of such intent.

Here's an example of where you'd use it: a function that returns some sort of unique class-based ID (for serialization, home-grown RTTI, etc.). There is no valid default. If a default were provided then 2 (or more) classes would end up with the same ID which would be very, very bad. Forcing derived classes to specify a function ensures that any derived object sets an ID.

I hope that's a good example.
Quote:Original post by Troll
Whenever you have a virtual function, you are telling other people that you intend classes to derive from the base class. Making a function pure virtual doesn't give greater indication of such intent.

Not necessarily. I'd make the distinction that a virtual function in a class informs the user that the class design supports derived class implementations and overrides, while a pure virtual function requires those implementations and overrides. At least, that's how I would read it.
:stylin: "Make games, not war.""...if you're doing this to learn then just study a modern C++ compiler's implementation." -snk_kid
pure virtual functions (pvf for short.. i'm lazy) are useful for definining interfaces. Its the closest substitute C++ has to Java's 'interface' and C#'s 'abstract class' keyword. You get the following differences from a standard virtual function:

1. ONE pvf is all it takes to make a class abstract/non-instantiable
2. pvf MUST be implemented in derived classes to make them instantiable. Derived classes are also abstract classes unless an implementation is provided for all inherited pvf.

in many C++ applications, object management is important. One way to track objects is to store all your objects in a list. However, if u take an array (for instance), an array is single-typed. An integer array only KEEPS integers and refuses to accept anything else. HOw then?
Thats where pure virtuals come in handy. You can keep an array of pointers to the abstract class and automagically you can store ANY derived class within that array.

So how is that different from a standard virtual function?... Not much, aside from the fact that it enforces that all types of a certain abstract base class WILL implement a custom behavior. Virtual functions allow you to fallback on a default implementation if you choose to do so.
- To learn, we share... Give some to take some -
Actually, you can provide an implementation for a pure virtual function if you wish. In that case a derived class can still use a default implementation, it just needs to be done explicitly rather than implicitly.
Pure virtual does not allow you to implement functionality that you otherwise couldn't. Rather it prevents you from compiling a program with certain errors. One of those is instantiating a class that should never be instantiated in a properly coded program. Another is failing to implement a function in a derived class that should be implemented in any properly coded program. You could provide a default, but if you do then you must catch those errors at runtime because they won't be caught at compile time.

An example is an abstract class representing a connection between two computers. The base class is an abstract representation of a connection. It provides a standard interface for your application regardless of the type of connection. Creating an instance of the base class does not actually make a connection to the other computer. Creating an instance of the base class is a mistake in the logic of your program. Implementing a new type of connection without supporting the functionality the program is using is a mistake as well. We established a connection, but we just threw away all that annoying data you told us to transmit.
Keys to success: Ability, ambition and opportunity.
So if i had a button class and i wanted to make multiple buttons of the class i could use a pure virtual function to make fresh buttons using the members of that base class? if so couldn't this just be done using class-constructors? what exactly are pure virtual functions?
Quote:Original post by GameMasterXL
So if i had a button class and i wanted to make multiple buttons of the class i could use a pure virtual function to make fresh buttons using the members of that base class? if so couldn't this just be done using class-constructors? what exactly are pure virtual functions?


I don't think so, in the way that I'm interpreting that. Basically, if you had a Button class that would just have the functions that any button you created would have such as changeColor() or onClick() or anything else that would apply, but would never be instantiated (button is way too general to be useful)that would be your base class and would (could) use pure virtual functions. The button will never be instantiated, will never have a color or be clicked, but its subclasses will, so we are making it mandatory that those subclasses are able to change color or be clicked.

You would have your derived classes SquareButton and CircleButton which would have to instantiate the functions changeColor() and onClick().

-Jeff
Well, first, when a class has virtual functions then it has a virtual table. The virtual table is a list of function pointers pointing to the virtual functions. A child class has a copy of that virtual table. The pointers to the virtual functions it overrode are replaced with pointers to it's own functions. It's at the same offset into the table as in the base, but it points somewhere else in the derived class. If the derived class adds new virtual functions they go at the end of the table. When you call a virtual function you load the address at a specific offset into the table and branch to that address. Which function you execute depends upon what you are pointing to and thus which virtual table you use.

A pure virtual function is a virtual function whose address is set to null in the virtual table. Thus the syntax of "=0" to specify a pure virtual function in C++. Well, if you try executing that function then you're gonna crash. So the compiler makes sure you can never actually do that. It does that by making sure you never use a virtual table with null pointers in it. Specifically, you cannot create an instance of a class with pure virtual functions. A derived class can override a pure virtual function and thus replace the null with a valid address in it's virtual table. If the derived class does that for all of the pure virtual functions in the base class then the compiler will allow you to create an instance of the derived class.

That's what a pure virtual function is. Does it have anything to do with creating an instance? Only to the extent that the compiler will not allow you to create an instance. Beyond that it is simly a matter of the program logic as to whether the constructor for the derived class uses the functions declared as pure virtual in the base.
Keys to success: Ability, ambition and opportunity.

This topic is closed to new replies.

Advertisement