views:

888

answers:

8

I'm learning about C++ in a class right now and I don't quite grok pure virtual functions. I understand that they are later outlined in a derived class, but why would you want to declare it as equal to 0 if you are just going to define it in the derived class?

+18  A: 

Briefly, it's to make the class abstract, so that it can't be instantiated, but a child class can override the pure virtual methods to form a concrete class. This is a good way to define an interface in C++.

Steven Sudit
I'd recommend changing: "...a child class can..." to "...a leaf class must...".
Richard Corden
I tried to stay intentionally vague to allow for the possibility of a child that overrides some but not all pure virtual methods, which results in an abstract base class that requires fewer overrides to become concrete. I wouldn't call it a leaf, however, because even a concrete child can have children of its own, and some of those can be abstract. In fact, a class can simultaneously override all previously pure virtual methods while declaring new ones. Given all this, I think it's probably better to leave the original, brief explanation, with this long-winded comment.
Steven Sudit
The issue is probably just one of of terminology. IMHO, a function is only pure virtual if it has not been implemented in one of the derived classes. In otherwords, if a class at any level still has a pure virtual function, then that class is still abstract. Hence my request. But I'd say that these comments probably explain things enough at this point! :)
Richard Corden
+9  A: 

This forces a derived class to define the function.

Jim Buck
A: 

The idea with abstract classes is that you can still have a variable declared with that type (i.e., it is the static type), but the variable actually refers or points to an actual concrete type (the dynamic type).

When you invoke a method in C++, the compiler needs to make sure that the method would be supported on that object.

By declaring the pure virtual function, you are putting a "placeholder" that the compiler can use to say "oh... I know that whatever ends up being referred to by this variable will accept that call" because the actual concrete types will implement it. However, you don't have to provide an implementation in the abstract type.

If you didn't declare anything, then the compiler would have no effective way of guaranteeing that it would be implemented by all subtypes.

Of course, if you're asking why you would want to make a class abstract, there's a lot of info around on that.

Uri
+4  A: 

Pure virtual methods in C++ are basically a way to define interfaces without requiring them to be implemented.

none
+3  A: 

To add to Steven Sudit's answer:

"Briefly, it's to make the class abstract, so that it can't be instantiated, but a child class can override the pure virtual methods to form a concrete class. This is a good way to define an interface in C++."

An example of this would be if you had a base class (perhaps Shape) that you use to define a number of member functions that its derived classes can use, but want to prevent an instance of Shape being declared and force users to use only the derived classes (which may be, Rectangle, Triangle, Pentagon, and so on)

RE: Jeff's answer above

Non-abstract classes can contain virtual member functions and be instantiated. In fact, for overloading member functions this is required as by default C++ doesn't determine the runtime type of a variable, but when defined using th virtual keyword, it will.

Consider this code (note, accessors, mutators, constructors, etc are not included for the sake of clarity):

class Person{
  int age;

  public:
    virtual void print(){
      cout << age <<endl;
    }
}

class Student: public Person{
  int studentID

  public:
    void print(){
      cout << age << studentID <<endl;
    }
}

Now when running this code:

 Person p = new Student();
 p.print();

without the virtual keyword, only the age would be printed, not the age and studentID as is supposed to happen for the Student class

(this example is based on a very similar one from c++ for java programmers http://www.amazon.com/Java-Programmers-Mark-Allen-Weiss/dp/013919424X )

@Steven Sudit: you are completely correct, I neglected to include the actual inheritance, doh! The accessors etc aren't included to keep things clearer, and I've made that more obvious now. 3-7-09: all fixed

chrisbunney
I believe your example is broken, as it doesn't include inheritance, and there's no way to ever set the values of the private data members. The idea behind it is correct, of course.
Steven Sudit
That's better, but still not quite right: the child class shouldn't have its own age data member.
Steven Sudit
Also, the instantiation at the bottom lacks parentheses around the constructor.
Steven Sudit
+5  A: 

Any class containing a pure virtual method will be abstract, that is, it cannot be instantiated. Abstract classes are useful for defining some core behavior that subclasses should share, but allowing (in fact, requiring) subclasses to implement the abstract individually.

An example of an abstract class:

class Foo {

    // pure virtual, must be implemented by subclasses
    virtual public void myMethod() = 0;

    // normal method, will be available to all subclasses,
    // but *can* be overridden
    virtual public void myOtherMethod();
};

A class in which every method is abstract can be used as an interface, requiring all subclasses to conform to the interface by implementing all methods contained in it.

An example of an interface:

class Bar {

    // all method are pure virtual; subclasses must implement
    // all of them
    virtual public void myMethod() = 0;

    virtual public void myOtherMethod() = 0;
};
Jeff L
I think you meant the first sentence to be "Any class containing a *pure* virtual method"....
Dan
I would probably add that an Abstract Base Class may contain not only implementations of methods, but data members as well. An interface should have neither. In C++, this is just a convention. In C# or Java, it's a rule.
Steven Sudit
+2  A: 

Imagine I want to model several kinds of shapes, and all have a well-defined area. I decide that every shape must inherit IShape ("I" for interface), and IShape will include a GetArea() method:

class IShape {
    virtual int GetArea();
};

Now the problem: how should I calculate the area of a shape if that shape doesn't override GetArea()? That is, what is the best default implementation? Circles use pi*radius^2, squares use length^2, parallelograms and rectangles use base*height, triangles use 1/2 base*height, rhombuses, pentagons, octagons, etc. use other formulas.

So I say "if you're a shape you must define a way to calculate the area, but damned if I know what that will be" by defining the method pure virtual:

class IShape {
    virtual int GetArea() = 0;
};
Max Lybbert
Wouldn't GetArea have to be declared virtual in both cases?
Steven Sudit
It needs to be declared virtual in the base class. Thanks for the correction.
Max Lybbert
+1  A: 
davidivins
I would suggest that the "name" data member in Student should be private, or at least protected. I would also recommend passing in the student by reference, not pointer. Finally, a real-world Student class would probably take the name in its constructor.
Steven Sudit
i concur with all of that. those were just oversights when i typed up this example real quick.
davidivins