Abstract Classes and Interfaces
Concrete classes are usable directly, while abstract classes describe what related types must provide.
Why Programs Need Their Own Types
Every piece of data a program works with has a type. The type tells the language what kind of thing the data is and which operations make sense on it. A language comes with some types already built in, but real programs usually model ideas that the language designers could not predict: an invoice, a sensor reading, a game character, a network connection. If a program can only use the built-in types, it has to describe these ideas with loose collections of plain values, and the code drifts away from the problem it is trying to solve.
What do you think happens?
A program needs to represent an invoice, which has a customer, line items, and a total. Which approach matches the program's vocabulary to the problem best?
Reveal answer
Define a new type that represents an invoice as a single meaningful unit
C++ lets you define new types of your own, so the program's vocabulary can match the problem it solves. Types defined this way are called user-defined types.
This article follows one idea through the chapter. We will watch what a user-defined type contains, how the three families of user-defined type differ, and how they connect to one another. Keep an eye on two goals as you read: abstraction and resource management.
What a User-Defined Type Bundles Together
A user-defined type is a type that the programmer defines, so that the program's vocabulary can match the problem it solves.
The idea is more than naming a new kind of thing. A user-defined type bundles data together with the operations that are allowed on that data. The rest of the program can then treat the new type as one meaningful unit instead of a loose collection of values. Think of the bundle as having two parts: the data it holds, and the operations the outside world may perform on that data.
- 1Identify an idea in the problem, such as an invoice or a sensor reading.
- 2Define a type whose name matches that idea, so the program's vocabulary mirrors the problem.
- 3Decide what data the type holds and which operations are allowed on that data.
- 4Use the type as a single unit everywhere else in the program.
Abstraction and Resource Management
C++ supports two broad goals in this part of the course. The first is abstraction. Abstraction hides the messy details of how something works behind a simpler interface, so that a user of a type can focus on what it does rather than how it does it. The second is resource management. Resource management handles things a program must acquire and later give back, such as memory or other limited items, in a disciplined way.
User-defined types are the main tool that brings these goals together. The type decides what the outside world can see and do. It can also control how the resources behind it are handled. So when you read about the three families below, ask two questions about each one: how does it hide detail, and how does it handle the resources it depends on?
The Three Families of User-Defined Type
This overview introduces three families of user-defined type: concrete classes, abstract classes, and class hierarchies. It does not work through each one in full detail. Instead, it gives the basic properties of each, the general implementation techniques behind them, and the language features that support them. The three families are not separate islands. All of them belong under the umbrella of user-defined types, and a class hierarchy is the structure that ties several related types together.
Tracing a Hierarchy from Abstract to Concrete
The source describes abstract classes as describing what related types must provide. To see this in a concrete setting, follow a small family of types that share a common idea. The names Shape, Circle, and Square below are generated for teaching; they are not taken from the source, but they show how the pieces of a class hierarchy fit together.
Reading the Shape Family
Given the Shape family, which types can a program create finished objects from, and what does Shape contribute?
- 1Apply the one question
Ask whether you can create a finished object straight from each type.
- 2Check Shape
Shape is the abstract class at the top. It describes what related types must provide, so it is not the type you create finished objects from.
- 3Check Circle and Square
Both are concrete classes. They build on Shape and are usable directly, so finished objects can be created from them.
- 4Relate the families
The hierarchy ties the family together: the abstract class sets the requirements, and the concrete classes meet them.
Circle and Square can be used to create finished objects. Shape describes what they must provide, and the class hierarchy is the structure linking all three.
Concrete Classes Versus Abstract Classes
Concrete and abstract classes are easiest to tell apart by asking one question: can you create a finished object straight from this type? A concrete class passes this test. An abstract class does not. Concrete classes are usable directly, while abstract classes describe what related types must provide. The table compares the two on the points this overview covers.
| Question | Concrete class | Abstract class |
|---|---|---|
| Can you create a finished object straight from it? | Yes | No |
| What role does it play? | Usable directly | Describes what related types must provide |
| How does it fit a hierarchy? | Can build on a related type and be used directly | Sets the requirements that related types must meet |
Concrete and abstract classes compared on the points covered in this overview.
Ask whether you can create a finished object straight from the type. If yes, it is a concrete class. If no, it is an abstract class that describes what related types must provide.
Mistakes Learners Make with the Three Families
Common mistake Treating every user-defined type as usable directly
What it looks likeAssuming Shape in the example above can be used to create a finished object just like Circle can.
Why it failsThe one question separates the families. An abstract class describes requirements rather than being a finished, usable type.
Do this insteadAsk whether you can create a finished object straight from the type before deciding how to use it.
Common mistake Thinking the three families are unrelated
What it looks likeTreating class hierarchies as a separate topic with no link to concrete or abstract classes.
Why it failsAll three belong under the umbrella of user-defined types, and a class hierarchy is the structure that ties related types together.
Do this insteadPlace each family under user-defined types and look at how the hierarchy connects them.
Common mistake Forgetting the two goals when reading each family
What it looks likeStudying a family only for its syntax and ignoring what it does for the outside world and for resources.
Why it failsUser-defined types exist to support abstraction and resource management, and each family serves those goals in a different way.
Do this insteadFor each family, ask how it hides detail and how it handles the resources behind it.
Check Your Understanding of the Families
A team is designing a program with three types: Vehicle, Car, and Truck. Vehicle describes what every kind of vehicle must provide, while Car and Truck are types the program creates finished objects from. Which family is Vehicle, which are Car and Truck, and how do they relate?
Hints
- Ask whether you can create a finished object straight from Vehicle.
- Think about what a class hierarchy does to related types.
- Remember that all three families sit under user-defined types.
Key Takeaways
- A user-defined type lets a C++ program define its own type, so the program's vocabulary matches the problem it solves, and it bundles data with the operations allowed on that data.
- C++ supports two broad goals here: abstraction, which hides details behind a simpler interface, and resource management, which acquires and gives back limited items in a disciplined way.
- The three families are concrete classes, abstract classes, and class hierarchies, all under the umbrella of user-defined types.
- Concrete classes are usable directly, while abstract classes describe what related types must provide. Ask whether you can create a finished object straight from the type to tell them apart.
- A class hierarchy is the structure that ties several related types together, linking abstract and concrete classes through derivation.