Concepts / Concrete Classes and Their Uses

Concrete Classes and Their Uses

Concrete classes, especially those with small representations, are used much like built-in types: as local variables, accessed by name, and copied around.

  • Programming

Two Questions Every New Object Raises

Whenever a program creates an object, two questions matter in practice. The first is where the object lives in memory, because that determines how long it stays available and how it is created. The second is how the rest of the program reaches it once it exists. The answers differ depending on whether the object belongs to a concrete class or to a class that takes part in a class hierarchy.

This article follows that difference step by step. By the end, you should be able to predict how a given object will be created and reached before you read the code that does it. Keep the two questions in mind as you go: where does the object live, and how does the program get to it?

Concrete Classes Behave Like Built-in Types

Concrete classes, especially those with small representations, are much like built-in types. You define an object of such a class as a local variable, you access it directly through its name, and you can copy it around the program. Nothing about the object requires you to go through an intermediate reference to reach it. The object is simply there under the name you gave it.

The key habit to notice is that a concrete object is handled the way you handle an int. You do not think about where it is stored. You simply name it and use it.

cpp
Notes on the code
  • Point is a small concrete type with no inheritance involved
  • a is defined as a local variable and used directly by name
  • b is a copy, so changing b does not change a

What do you think happens?

After b.x is set to 10, what is the value of a.x?

  • 1

  • 10

  • It is undefined

Reveal answer
Answer:

1

b is a separate copy of a. Assigning to b.x changes only the copy, so a.x keeps its original value of 1.

Where Hierarchy Objects Live

Classes in class hierarchies follow a different pattern. Their objects are typically allocated on the free store using new. The object itself is created by new, and the name you hold is a handle that leads to the object rather than the object itself. The local name is not where the object's data sits.

The diagram below shows this split. On one side is a local pointer variable that belongs to the function. On the other side is the object it refers to, which lives on the free store. The variable and the object are two separate things, connected by the pointer.

Local pointer pholds a handleCircle objectcreated by newrefers to
Where does an object created with new live compared with a local variable, and what stays with the function versus on the free store?

Why a Name Gives Only a Handle

Notice what this changes. The object is not reached by the name of a local variable sitting next to it. It is reached by following the pointer. Objects in class hierarchies are typically accessed through pointers or references rather than by their names alone.

A reference works in the same spirit. It gives you another way to refer to the object without making a copy of it. So when several names refer to the same hierarchy object, they all lead to one object on the free store, and no duplicate is created.

Pointer slocal name that leads tothe objectShape objectallocated with newReference ranother way to refer to itpoints torefers to
Why can a name not refer to a hierarchy object directly, and how does a pointer or reference connect a variable to the object on the free store?

Comparing the Two Usage Patterns

The source puts the contrast in a single sentence: concrete classes are much like built-in types, whereas classes in hierarchies follow a different pattern. The table lays the two patterns side by side. Each row names one aspect of use, so you can read down either column to see the full pattern.

AspectConcrete class (small representation)Class in a hierarchy
How the object is definedAs a local variableCreated with new on the free store
How it is reachedDirectly by its nameThrough a pointer or reference
CopyingCopied around the program like a built-in valueReached through the handle rather than copied by name
Where the name sitsThe name holds the objectThe name is a handle leading to the object

Typical usage of concrete classes compared with classes in hierarchies

Tracing a Shape Reader Function

The source introduces the pattern with a function that reads data describing shapes from an input stream and constructs the appropriate Shape objects. The point of the example is that the program does not know in advance which concrete kind of shape each piece of data describes. It decides while reading, and it creates the matching object.

Because these objects belong to a class hierarchy, each one is allocated on the free store with new, and the function keeps a pointer to it so the object can be reached later. The program below is an original illustration of that pattern, written to show the flow clearly.

cpp
Output
12.5664
9
Walk through it
  1. 1
    read_shapes reads one kind and one size at a time from the input stream.
  2. 2
    When the kind is circle, new creates a Circle on the free store and its pointer is stored in shapes.
  3. 3
    When the kind is square, new creates a Square and its pointer is stored the same way.
  4. 4
    The function returns the vector of pointers, so the objects remain available after the function ends.
  5. 5
    main loops over the pointers and calls area through each one, reaching every object by following its pointer.
Notes on the code
  • read_shapes decides the concrete kind from each piece of input
  • new creates each Circle or Square on the free store
  • the vector keeps pointers, so the function can return handles to the objects
  • main reaches each object through its pointer p

The sequence diagram below traces the order of these steps. It shows which part of the program holds the pointer to each created shape and when the object is reached afterward.

Input streamshape kinds and sizesread_shapesdecides the kind whilereadingFree storeobjects created with newmainholds the pointers1: read kind and size2: new Circle or Square3: return vector of pointers4: area through each pointer
In what order do the reading, construction, and later access steps happen, and which part of the program holds the pointer to each created shape?

Common Mistakes With Hierarchy Objects

  • Common mistake

    Treating a hierarchy object like a concrete local variable

    What it looks like

    Shape s; defined as a plain local variable and then used as if it were a Circle

    Why it fails

    Hierarchy objects are typically allocated on the free store with new and reached through pointers or references, not used directly by name alone.

    Do this instead
    Create the object with new and keep a pointer to it, as in Shape* p = new Circle(2.0);
  • Common mistake

    Assuming a copy is made when a second name is introduced

    What it looks like

    Shape* q = p; and then expecting q to be a separate object

    Why it fails

    A pointer or reference gives another way to refer to the same object. It does not make a copy of the object.

    Do this instead

    Think of q and p as two routes to one object; a change made through either is seen through both.

  • Common mistake

    Losing the pointer to an object created with new

    What it looks like

    Calling new inside a function and never storing the returned pointer anywhere

    Why it fails

    Without a stored pointer, the program has no way to reach the object afterward, which is why the source keeps a pointer to each created shape.

    Do this instead

    Store the pointer in a container or variable that lives as long as the object is needed.

  • Common mistake

    Expecting a concrete class and a hierarchy class to follow the same usage rules without checking which pattern applies

Practice Tracing the Shape Reader

MEDIUM

Using the read_shapes program above, suppose the input stream contains the text: square 4.0 circle 1.0. Predict the order in which new is called and the order in which area is called on the stored pointers. Then state which part of the program holds the pointer to each object after read_shapes returns.

Hints
  • Read the input one kind and size pair at a time, from left to right.
  • A square triggers new Square and a circle triggers new Circle.
  • After read_shapes returns, the vector in main is the only thing holding the pointers.

Key Takeaways

  • Concrete classes, especially those with small representations, are used much like built-in types: you define them as local variables, access them directly by name, and copy them.
  • Objects in class hierarchies are typically allocated on the free store using new, and the name you hold is a handle that leads to the object.
  • Hierarchy objects are typically accessed through pointers or references rather than by their names alone; a reference gives another way to refer to the object without copying it.
  • A function that reads shape data can decide each concrete kind while reading, construct the matching object with new, and keep a pointer so the object can be reached later.

Related concepts

More concepts starting with C