Inheritance and Class Hierarchies
If the answer is yes, the class is concrete.
Why Programs Define Their Own Types
A C++ program works with types. Every value and every object in a program belongs to some type, and the type tells the program what kind of thing it is dealing with. Some types come with the language itself. The built-in number types are the standard example. Programmers do not write those types; they simply use them.
Real programs, however, deal with ideas that the language cannot know about in advance: a bank account, a shape, a sensor reading. C++ lets you define new types of your own for exactly this purpose. These are called user-defined types. A user-defined type lets you model one idea from your problem as a single named type in your program. Once you have that named type, the rest of the program can talk about bank accounts, shapes, or sensor readings directly instead of juggling loose collections of numbers.
This article follows one idea through a short sequence: first, how user-defined types differ from built-in ones; then, the two basic families of user-defined types, concrete classes and abstract classes; and finally, how related types are arranged into a class hierarchy through inheritance. At each stage you will check a claim against a concrete picture before moving on.
Built-in Types and User-Defined Types
The difference between the two kinds of type comes down to where the definition comes from. A built-in type is supplied by the language itself, such as the built-in number types. A user-defined type is one the programmer defines, so the programmer decides what the type represents and what it is named.
| Property | Built-in type | User-defined type |
|---|---|---|
| Where the definition comes from | The language itself | The programmer |
| Typical examples named in the source | The built-in number types | A bank account, a shape, a sensor reading |
| What it models | General-purpose values the language provides | One idea from the problem being solved |
| Who names it | The language | The programmer, as a single named type |
Built-in and user-defined types, as the source describes them
Concrete Classes and the Can-I-Create-It Test
A concrete class is a class that is not abstract and can be instantiated, so objects can be created from it.
The key test for a concrete class is simple: can you make an object from it? If the answer is yes, the class is concrete. Most of the classes you write to represent a single, complete idea in your program are concrete. When you create an object from a concrete class, the object is an actual instance of that type, ready to hold data and respond to the operations the class defines.
Concrete means the class is complete enough to be used directly. If you can write the line that creates an object of it, it is concrete.
Abstract Classes as Common Bases
An abstract class cannot be instantiated on its own. Its purpose is to serve as a common base for other classes that inherit from it.
The contrast with a concrete class is the important part. A concrete class answers the question can I create an object of this type with yes. An abstract class answers it with no. You do not create objects from the abstract class itself. Instead, you create objects from the classes that inherit from it, because those are the classes that describe complete things.
Keep the two columns in the diagram apart in your mind. The same question, whether an object can be created from this class, produces yes for a concrete class and no for an abstract class.
Tracing a Shape Hierarchy
A class hierarchy gives related types a shared structure. A general class sits near the top, and more specific classes sit below it, each inheriting from the class above it. Read the hierarchy from the top down and each step adds specificity. Read it from the bottom up and each step generalizes.
Work through the small example below, which is a generated illustration of this idea. Shape is the general idea. Circle, Square, and Triangle are the specific kinds of shape, and each inherits from Shape. Trace the links from the top: the three specific classes all sit one level below Shape, and each one is connected to it by an inheritance link.
Notice what the diagram does and does not say. It shows that Circle, Square, and Triangle inherit from Shape. It does not, by itself, tell you whether Shape can have objects created from it. That is a separate question, and you answer it by applying the can-I-create-it test from the previous sections. The source notes that abstract classes often appear near the top of a hierarchy because they describe what the related classes have in common, while concrete classes often appear at the bottom, where complete objects are created. The word often matters: position in the hierarchy is a hint, not a proof.
Worked Example: Classifying a Class
Deciding whether a class is concrete or abstract
A program defines a class called Vehicle. The design intends that a Vehicle object should never exist on its own; the only things that should be created are Car and Bike objects, each of which inherits from Vehicle and represents a complete, usable thing. Is Vehicle concrete or abstract?
- 1Apply the key test
The key test asks whether you can make an object from the class. The design says a Vehicle object should never exist on its own, so the answer is no.
- 2Check the role of the class
Vehicle is meant to be inherited by other classes, which is the role the source assigns to an abstract class: a common base for classes that derive from it.
- 3Check the derived classes
Car and Bike are the classes whose objects are actually created. They sit below Vehicle in the hierarchy, which matches the pattern of concrete classes at the bottom.
- 4Reach the classification
Vehicle cannot be instantiated and exists to be inherited, so it is abstract. Car and Bike are concrete, because objects can be created from them.
Vehicle is an abstract class. Its justification is that objects cannot be created from it, and its purpose is to serve as a common base for Car and Bike.
Mistakes Learners Make with Hierarchies
Common mistake Assuming a class is abstract just because it sits near the top of a hierarchy
What it looks likeSeeing Shape at the top of a tree and concluding that Shape can never have objects.
Why it failsThe source says abstract classes often appear near the top, but the word often is deliberate. Position is a hint, not a rule.
Do this insteadApply the can-I-create-it test directly to the class in question, and use position only as supporting evidence.
Common mistake Confusing the question of creation with the question of inheritance
What it looks likeReasoning that because Circle inherits from Shape, an object of Circle must also be an object of a Shape-only type that you can create directly.
Why it failsInheritance links the classes together in a hierarchy. Whether an object can be created from a class is a separate property that you test for each class.
Do this insteadAsk two separate questions: how the class is related to others through inheritance, and whether objects can be created from that class.
Common mistake Treating every class you write as abstract
What it looks likeMaking a class for a single complete idea, such as a bank account, and then being unable to create objects from it.
Why it failsThe source says most classes that represent a single, complete idea are concrete, and the key test for a concrete class is that objects can be created from it.
Do this insteadFor a class that models one complete idea, confirm that you can create an object from it. If you can, it is concrete.
Common mistake Mixing up built-in types and user-defined types, as though a programmer-defined type came with the language
Practice Classifying Classes
A program has a class called Sensor, which exists only so that TemperatureSensor and PressureSensor can inherit from it. The program creates objects only of TemperatureSensor and PressureSensor. Classify Sensor as concrete or abstract, and justify your answer using the key test from this article.
Hints
- Start with the key test: can you make an object from Sensor?
- Check the purpose the description gives for Sensor and compare it with the definition of an abstract class.
- Look at which classes are the ones whose objects the program actually creates.
Key Takeaways
- A user-defined type lets a programmer model one idea from a problem, such as a bank account, a shape, or a sensor reading, as a single named type; built-in types such as the number types come with the language itself.
- A concrete class is not abstract and can be instantiated, so objects can be created from it; the key test is whether you can make an object from the class.
- An abstract class cannot be instantiated on its own and exists to be inherited by other classes, which is why objects are created from the classes that derive from it.
- A class hierarchy organizes related classes through inheritance, with general classes above specific ones; abstract classes often sit near the top and concrete classes often sit at the bottom, but the test is always whether objects can be created.