Concepts / Inheritance and Derived Classes

Inheritance and Derived Classes

A class that contains a pure virtual function, marked with the =0 suffix, is an abstract class.

  • Programming

A Container That Promises Operations

Imagine a class that describes a container. It stores no data itself. Instead, it lists the operations any container must support, such as reporting its size and adding a value. The interesting question is not what the class does, but which of these operations it promises to provide and which of them it leaves for someone else to provide. This lesson starts from a declaration like that and works outward from it. Keep one question in mind as you read: which member functions does the class promise to provide, and which does it leave unfinished?

What do you think happens?

The Container class declares two operations with no body and no implementation. Can you write a line such as Container c; and create an object from it?

  • Yes, it can be created

  • No, it cannot be created on its own

Reveal answer
Answer:

No, it cannot be created on its own

The restriction does not come from the class being large or from missing data members. It comes from the pure virtual functions the class declares. A class that contains a pure virtual function is abstract, and an abstract class cannot be used to create an object on its own. It serves as an interface for derived classes.

Reading the Container Declaration

The following Container declaration is an illustrative example written for this lesson. It is an interface: it names the operations and their signatures, but it provides no implementation for the two operations that matter most. Read each line and ask whether the function has a body.

Code walkthrough
class Container {
public:
    virtual int size() const = 0;
    virtual void push(int value) = 0;
    virtual ~Container() {}
};
  1. 1
    The class has no data members. Its abstractness is not caused by missing data.
  2. 2
    Two member functions end in = 0 with no body. These are the pure members.
  3. 3
    The destructor has a body, so it is an ordinary virtual function and not a pure one.
  • virtual int size() const = 0; declares a pure virtual function. The virtual keyword allows redefinition in a derived class, and the = 0 suffix makes it pure.
  • virtual void push(int value) = 0; is the second pure virtual function. Both operations are requirements placed on future code rather than complete functions.
  • virtual ~Container() {} is a virtual destructor with a body. It is virtual but not pure, so it does not make the class abstract.
virtualfunction may be redefinedin a derived classint size() constname, parameters, and constqualifier= 0marks the function as purevirtual;no body follows, only adeclarationfollowed byfollowed byfollowed by
Which parts of the declaration mark a function as pure virtual, and what does the declaration leave out?

A pure virtual function is recognized by two things together: the virtual keyword and the = 0 suffix, with no body supplied. Remove either the suffix or the body idea and the function is no longer pure. The ordinary members of the class, such as a destructor with a body, are not pure, even though they are virtual.

Virtual Versus Pure Virtual

Definition

A virtual function is a function declared with the word virtual, which means that it may be redefined later in a class derived from this one. A pure virtual function is a virtual function marked with the suffix = 0, which means that some class derived from the interface must define it. A class that contains a pure virtual function is an abstract class.

FeatureVirtual function with a bodyPure virtual function
Marked with virtualYesYes
Marked with = 0NoYes
Can a derived class redefine itYesYes
Does a derived class have to provide a definitionNoYes
Makes the class abstractNoYes

Both kinds of function can be redefined, but only the pure kind forces a derived class to provide a definition.

Rules That Decide Whether a Class Is Abstract

To decide whether a class is abstract, you ask two questions in order. First, does the class itself declare a pure virtual function? If yes, the class is abstract. Second, if the class declares no new pure virtual function, does it inherit one that it never overrides? If yes, the class is still abstract, because the pure virtual function it inherited has not been given a definition. Only when no pure virtual function remains is the class concrete.

Examine a classDeclares a purevirtual?AbstractInherits a purevirtual notoverridden?Concretecheckyesnoyesno
Which checks decide whether a class is abstract or concrete, given its own declarations and the pure virtual functions it inherits?

Notice that the second question is the one beginners miss. A derived class can contain no pure keyword at all and still be abstract, because it inherited a pure virtual function that it did not define. The key question is always whether every pure virtual function has been given a definition in the class being examined.

Why the Interface Cannot Become an Object

An interface becomes useful when a class derives from it and supplies the missing functions. The Container declaration sets out what every container must be able to do, but it is not itself a working container. Its pure virtual functions have no bodies, so there is no complete behavior to run when an object is used. This is why the language refuses to build an object from the interface itself. Objects are built only from the derived class, which takes responsibility for making the operations actually work.

Think of the interface as a requirement placed on future code. The base class names the operations, and each derived class that wants to be instantiated must answer that requirement for every pure virtual function it inherited. The interface is never the thing that gets instantiated; the completed derived class is.

Building a Concrete Derived Class

The following derived class is an illustrative example written for this lesson, not taken from the source. It keeps its elements in a plain array and provides a definition for both pure virtual functions. The array has a fixed size and performs no bounds check; this is kept deliberately short so that the focus stays on inheritance.

Code walkthrough
class ArrayContainer : public Container {
    int data[100];
    int count = 0;
public:
    int size() const override { return count; }
    void push(int value) override { data[count] = value; ++count; }
};
  1. 1
    The derived class declares no new pure virtual functions.
  2. 2
    It defines both inherited pure virtual functions, so no pure member remains.
  3. 3
    Because nothing pure is left, objects of ArrayContainer can be created, which is not possible for Container.
  • class ArrayContainer : public Container names the base class, so this class derives from the interface.
  • int size() const override { return count; } supplies a definition for the first pure virtual function.
  • void push(int value) override { ... } supplies a definition for the second pure virtual function.
Containersize and push both purePartly overriddensize defined, push stillpureArrayContainerno pure virtual functionsleftoverride sizeoverride push
How does a derived class move from abstract to concrete as each inherited pure virtual function is overridden?

Each override removes one pure requirement from the list. The class is abstract until the list is empty, and only then can an object be created from it. The derived class must therefore match the interface completely before it can be used as an object.

Tracing a Class That Stays Abstract

Now consider a derived class that defines only one of the two pure virtual functions. This is an illustrative example written for this lesson.

cpp
Notes on the code
  • Broken overrides size but says nothing about push.
  • push is still the pure virtual function inherited from Container.
Worked example

Checking whether Broken can be instantiated

Can an object of type Broken be created?

  1. 1
    List the inherited pure virtual functions

    Container declares size and push as pure virtual, so Broken inherits both.

  2. 2
    List the definitions Broken supplies

    Broken overrides size only. It provides no definition for push.

  3. 3
    Check what remains pure

    push has no definition in Broken, so it is still a pure virtual function, and Broken still contains one.

  4. 4
    Decide the class kind

    Broken is abstract, so an object of Broken cannot be created on its own.

Result

Broken is abstract. Its missing definition for push is the single problem to fix before it can be instantiated.

Debugging

When a derived class fails to become usable, ask one question: which pure virtual function from the interface is still missing a definition? In this case the answer is push. Locating that one function usually explains the whole problem, and adding a push override to Broken would make it concrete.

Mistakes Learners Make

  • Common mistake

    Deciding a class is abstract because it is large or has no data members

    What it looks like

    Container has no data members and only two member functions, yet it is abstract.

    Why it fails

    Abstractness comes from the pure virtual functions, not from the size of the class or from what data it stores.

    Do this instead

    Look for the = 0 suffix on a virtual function, not for the number of members.

  • Common mistake

    Treating a virtual function with a body as pure

    What it looks like

    virtual ~Container() {} is virtual and has a body.

    Why it fails

    A function with a body is not pure, and a virtual destructor with a body does not make a class abstract.

    Do this instead

    Only the = 0 suffix on a virtual function makes it pure.

  • Common mistake

    Overriding some pure virtual functions and expecting the class to be instantiable

    What it looks like

    Broken overrides size but leaves push undefined, and an object of Broken is then attempted.

    Why it fails

    Every inherited pure virtual function must be defined before the class can be created as an object.

    Do this instead

    List every inherited pure virtual function and confirm that each one has a definition in the derived class.

  • Common mistake

    Trying to create an object from the interface itself

    What it looks like

    Writing Container c; as if Container were a usable class.

    Why it fails

    The interface declares operations without implementing them, so it cannot serve as a complete object.

    Do this instead

    Create objects only from a derived class that defines all of the pure virtual functions.

Practice: Classify Two Classes

MEDIUM

A class Shape declares two members: virtual double area() const = 0; and virtual void draw() const = 0;. A class Circle derives from Shape and overrides only area. Is Circle abstract, and can an object of Circle be created? Explain which function decides the answer. Then say what Circle would need to add for an object to be created.

Hints
  • Start by listing every pure virtual function that Circle inherits from Shape.
  • Ask which of those functions Circle defines, and which it leaves undefined.
  • A class with any remaining pure virtual function is abstract, no matter how many functions it did define.
EASY

Write a derived class Square from Shape that defines both area and draw, and state in one sentence whether an object of Square can be created.

Hints
  • Both pure virtual functions must have definitions in Square.
  • Once no pure virtual function remains, the class is concrete.

Key Takeaways

  • A pure virtual function is a virtual function marked with = 0, and a class that contains one is an abstract class.
  • An abstract class cannot be used to create an object on its own, because it serves as an interface that derived classes must complete.
  • A virtual function with a body, such as a virtual destructor, is not pure and does not make a class abstract.
  • A derived class must define every pure virtual function it inherits before objects of that class can be created.
  • To predict whether a class is abstract, check whether it declares a pure virtual function or inherits one it never overrides.

Related concepts

More concepts starting with I