Concepts / Pointers to Objects in Collections

Pointers to Objects in Collections

Each pointer refers to some concrete figure, whether that figure is a circle, a square, or a triangle.

  • Programming

A Drawing Program Needs One Collection

Imagine you are building a drawing program. Users can place circles, squares, and triangles on a canvas, and the program needs to keep all of them in one collection. Once the figures are stored, a practical question follows: how do you write a single function that processes every item in that collection, without writing a separate function for each kind of figure?

The answer depends on a design decision about the base concept that all those figures share. If every figure is a Shape, the real question becomes what a Shape itself should be. This article approaches that question from the side of design: what kind of class Shape should be, and what it can honestly promise to the functions that use it.

Why Different Figures Cannot Share One Slot Type

Before deciding what goes into the collection, it helps to see what the collection cannot hold. The figures in the drawing program are different concrete types. A circle, a square, and a triangle are not the same kind of value, so the collection cannot treat the figures themselves as one uniform kind of item.

What do you think happens?

Can one collection hold a Circle object and a Square object directly, as two uniform items of the same kind?

  • Yes, because both are shapes

  • No, because the figures are different concrete types and cannot be stored as one uniform kind of value

Reveal answer
Answer:

No, because the figures are different concrete types and cannot be stored as one uniform kind of value

The source states that the collection cannot store the figures themselves as one uniform kind of value. Instead, it stores pointers to shapes. Every element is then a pointer to a Shape, while each pointer refers to some concrete figure.

The solution is to make the collection uniform at the level of the pointer. Each pointer refers to some concrete figure, whether that figure is a circle, a square, or a triangle. The collection itself is uniform because every element is a pointer to a Shape. The diagram below shows the relationship between the collection, its pointers, and the objects they refer to.

Read the diagram from top to bottom. The collection is the single container. Each pointer in the middle row is a stored element. Each pointer leads down to one concrete figure. The collection never needs to know which figure sits at the bottom of a given pointer; it only needs each element to be a pointer to a Shape.

What Makes a Class Abstract

Definition

An abstract class is not meant to be instantiated on its own. It exists to serve as a base for other classes.

Shape is the standard example. There is no such thing as a generic shape sitting in a drawing: every real shape is a particular kind of shape, such as a circle or a square. So Shape works as an abstract class. Its job is to name the common idea of a shape and to serve as the common base that the specific figures build on.

Notice the wording of the source definition. It does not say an abstract class has no purpose. It says it is not meant to be instantiated on its own. That distinction matters: a Shape can be the type that every figure is described by, even though no drawing ever contains a plain Shape that is nothing in particular.

How Shape Relates to Its Derived Figures

In the inheritance hierarchy, Shape sits above the concrete figures. Circle, square, and triangle are derived from it. The diagram shows the family tree. Notice what it does not show: the fields inside each figure. Each derived class brings its own details, and the abstract base sits above them as the shared name and shared contract.

The contrast in this tree is intentional. The hierarchy is a relationship between kinds, so Shape is the general kind and the figures are specific kinds beneath it. The stored data stays specific to each kind. Shape is the only class in the tree that cannot be created as an object, while Circle, Square, and Triangle are the figures a drawing actually contains.

Almost Nothing Is Shared in Storage

It is tempting to think of a base class as a template that fills in fields for every subclass. A circle has a radius, a square has a side length, and a triangle has three sides, so one might expect a common base to hold a shared set of numbers. The abstract class idea runs the other way. Because the representations differ so much, the base is valuable for what it allows callers to do, not for what it stores.

The source states the point directly: as far as representation is concerned, nothing except the location of the pointer to the vtbl is common for every Shape. In other words, the Shape part of each object carries no common fields that all shapes must store in the same way. What the derived classes share is the interface through which they are used, not a common layout of stored values.

Key point

A base such as Shape provides a shared interface rather than shared stored data. Its promise is what every figure supports, not what every figure holds.

This explains why the base can be abstract without being a container. A circle needs a radius, a square needs a side length, and a triangle needs three sides. Those requirements are different, so the derived classes keep their own stored details. The one thing the source says is common to every Shape is the location of the pointer to the vtbl, and that is part of how each object is organized rather than a field the programmer designs.

Tracing One General Function Over the Collection

Worked example

One loop over a collection of mixed figures

The drawing program keeps a collection of pointers to Shape. The collection holds a circle, a square, and a triangle. Explain how one general function can process every item without a separate function for each figure type.

  1. 1
    Step 1: Identify what the collection holds

    The collection does not hold the figures as values. It holds pointers, and every element is a pointer to a Shape. Each pointer refers to some concrete figure.

  2. 2
    Step 2: Write one general function

    The function takes the collection and works on each element in turn. It does not need to know whether a given pointer refers to a circle, a square, or a triangle.

  3. 3
    Step 3: Rely on what every Shape promises

    Because each pointer leads to a Shape, the function can use the operations the abstract class promises. Those operations are the shared interface, which is the reason the base class exists.

  4. 4
    Step 4: Process mixed items in one pass

    The same code handles the circle pointer, the square pointer, and the triangle pointer. The function never has to be rewritten when a new concrete figure is added, as long as that figure is still a Shape.

Result

One general function manipulates the whole collection because the collection is uniform at the pointer level. The concrete figure behind each pointer can differ, and the function does not need to know which one it is.

Storing Values Versus Storing Pointers

The difference between storing figures by value and storing pointers to them is the reason the design works. The table below compares the two approaches using only the ideas the source supports.

QuestionStoring figures by valueStoring pointers to shapes
What the collection holdsThe figures themselves as one uniform kind of valuePointers, where every element is a pointer to a Shape
Can it mix circles and squaresNot as one uniform kind of value, according to the sourceYes, each pointer can refer to a different concrete figure
What the general function works withThe stored values themselvesPointers that lead to a Shape and its shared interface
Role of the abstract baseDoes not give one uniform storage type for mixed figuresGives the shared interface every element can rely on

Comparing value storage with pointer storage for a collection of mixed figures

The contrast answers the question of why storing pointers keeps the behavior of the derived classes available. Each pointer still refers to a concrete figure, so the figure's own details remain where they belong, while the collection stays uniform at the level of Shape.

Mistakes With Abstract Bases and Collections

  • Common mistake

    Treating an abstract class as an ordinary class that can be created on its own

    What it looks like

    Creating a plain Shape object to represent a figure in the drawing

    Why it fails

    An abstract class is not meant to be instantiated on its own. Every real shape is a particular kind of shape, so there is no generic shape in the drawing.

    Do this instead

    Create objects of the concrete derived figures, such as a circle or a square, and let them be used through the Shape interface.

  • Common mistake

    Expecting the base class to hold the shared data for every figure

    What it looks like

    Assuming Shape must store a radius or a side length for all figures

    Why it fails

    Representations differ so much across figures that the base provides a shared interface rather than shared stored data.

    Do this instead

    Keep the specific stored details in each derived class and rely on the base for the common interface.

  • Common mistake

    Trying to store different figures directly as one uniform kind of value

    What it looks like

    Expecting one collection of figure values to hold a circle and a square side by side

    Why it fails

    The source says the collection cannot store the figures themselves as one uniform kind of value because they are different concrete types.

    Do this instead

    Store pointers to shapes, so every element is a pointer to a Shape while each pointer refers to a concrete figure.

  • Common mistake

    Writing a separate general-purpose function for every figure type instead of one function over the shape pointers

Checking Your Understanding

MEDIUM

A drawing program stores a circle, a square, and a triangle in one collection of pointers to Shape. Explain in your own words why one general function can process all three without being rewritten for each figure, and name the one thing the source says every Shape has in common in its representation.

Hints
  • Ask what each element of the collection is, not what the figure is.
  • Think about what the function is allowed to rely on: the promise every Shape supports.
  • The source names the location of the pointer to the vtbl as the only representation shared by every Shape.
EASY

Without looking back, state the reason an abstract class such as Shape is not instantiated on its own, and then state why the base class is still useful.

Hints
  • The definition says it is not meant to be instantiated on its own and exists to serve as a base for other classes.

Key Takeaways

  • An abstract class such as Shape is not meant to be instantiated on its own. It exists to serve as a base for other classes that name the common idea of a shape.
  • Shape shares almost no stored representation across its derived classes. As far as representation is concerned, nothing except the location of the pointer to the vtbl is common for every Shape.
  • The base provides a shared interface rather than shared stored data, so the derived figures keep their own details such as a radius, a side length, or three sides.
  • A collection cannot hold different concrete figures as one uniform kind of value, so it holds pointers to shapes, and every element is a pointer to a Shape.
  • Because each pointer leads to a Shape and every Shape supports the promised operations, one general function can work over the whole collection regardless of which figure each pointer refers to.

Related concepts

More concepts starting with P