Classes and Access Modifiers in C++
The first design of C++, called C with Classes, included function declarations with argument type checking and implicit conversions, classes with public and private parts, derived classes, and constructors and destructors.
A Design Built Around Object Lifetimes
C++ began as an extension of an older language, not as a finished language. Its first design was called C with Classes. Among its features were typed function declarations, implicit conversions, classes with public and private parts, derived classes, and constructors and destructors. Before looking at that list, consider this question: which feature might affect both the moment an object is created and the moment it is finished?
What do you think happens?
For one object, what is the order of setup, use of its member functions, and cleanup?
Reveal answer
The constructor sets things up, member functions can use that environment, then the destructor reverses the setup.
The constructor creates the execution environment for the class's member functions. The destructor reverses that setup when the object is finished.
One Object from Setup to Cleanup
For a single object, the key sequence is straightforward: its constructor prepares the environment, member functions operate within that environment, and its destructor reverses the setup when the object is finished. The constructor and destructor are a pair that mark the beginning and end of this setup.
The First Feature Set
C with Classes combined several capabilities rather than presenting them as unrelated tools. Function declarations described a function's name, the types of values expected for its parameters, and its return type. Argument type checking let the compiler compare call arguments with the declared parameter types so that a mismatch could be caught before the program ran. The design also included implicit conversions: the language could automatically convert a supplied value when a different type was expected.
Classes used public and private parts to separate the interface available to other code from implementation details kept inside the class. Derived classes were also included: they were built on a base class and could add to it. Constructors and destructors handled the setup and reversal associated with an object's life. The early design also used macros as a primitive form of parameterization.
| Early feature | Contribution described in the design |
|---|---|
| Function declarations | Name a function, its expected argument types, and its return type. |
| Argument type checking | Compares values supplied in a call with the declared parameter types. |
| Implicit conversions | Allows the language to convert a supplied value automatically when another type is expected. |
| Classes with public and private parts | Separate the interface available to other code from the implementation kept inside the class. |
| Derived classes | Build a class on top of a base class and allow additions to it. |
| Constructors and destructors | Establish and reverse the environment needed by a class's member functions. |
| Macros | Provide a primitive form of parameterization. |
The capabilities included in the first C++ design, called C with Classes.
The Class Boundary
The public and private parts of a class define a boundary. Public members make up the interface that outside code is allowed to use directly. Private members are reserved for the class itself and belong to its implementation. This separation gives the class author room to change internal details without requiring changes in code that uses the class, provided the public interface remains the same.
Building from a Base Class
A derived class is built on top of an existing class, called its base. It takes on the base class's structure and can add to it. This makes derived classes a capability built on the class mechanism itself: there must first be a class whose interface and implementation are divided into public and private parts.
Resource Management Across a Lifetime
Constructors and destructors also provide a way to connect resource management to an object's lifetime. A resource is something a program must acquire and later give back. The constructor runs as the object is created, so a class can associate acquiring a resource with that beginning. The destructor runs when the object is finished, so the class can associate releasing the resource with that end.
A Resource-Using Object
Trace the constructor and destructor for a hypothetical class called Notebook. Suppose its constructor acquires a resource and its destructor releases that resource. What happens as one Notebook object is created, used, and finished?
- 1Creation
The Notebook object comes into being, and its constructor runs to prepare the environment for its member functions.
- 2Acquisition
For this generated example, the class associates acquiring a resource with the constructor's setup.
- 3Use
Member functions can run using the environment established by the constructor.
- 4Finish
When the object is finished, its destructor runs and reverses the setup, including the example's resource-release step.
The lifecycle connects setup and resource acquisition at creation with reversal and resource release when the object is finished.
Mistakes to Avoid
Common mistake Treating constructors and destructors as unrelated features.
Why it failsThey mark opposite ends of the setup that member functions depend on: the constructor creates the environment and the destructor reverses it.
Do this insteadThink of them as a lifecycle pair, from setup to cleanup.
Common mistake Assuming type checking means the language never converts an argument.
Why it failsThe early design included both argument type checking and implicit conversions.
Do this insteadKeep the ideas distinct: calls are checked against declared types, and the language may also perform implicit conversions.
Common mistake Treating public and private parts as interchangeable.
Why it failsThe class uses them to separate the interface available to outside code from its internal implementation.
Do this insteadUse public for the class's outside-facing interface and private for details reserved for the class itself.
Common mistake Describing a derived class as unrelated to its base.
Why it failsA derived class is built on a base class and takes on its structure, with room to add to it.
Do this insteadDescribe the relationship as building on an existing base class.
Practice the Lifecycle
A class's constructor prepares an environment for its member functions, and its destructor reverses that setup. In a short explanation, trace one object's lifecycle and show where a resource could be acquired and released. Then name two other capabilities included in C with Classes and state what each contributes.
Hints
- Begin with the constructor and end with the destructor.
- Place member-function use between setup and reversal.
- For the other capabilities, consider function declarations, public and private class parts, derived classes, and macros.
Key Takeaways
- C with Classes combined function declarations with argument type checking and implicit conversions, classes with public and private parts, derived classes, constructors and destructors, and macros used for primitive parameterization.
- Public members form a class's outside-facing interface; private members are implementation details kept for the class itself.
- A derived class is built on a base class, takes on its structure, and can add to it.
- A constructor prepares the environment for member functions, while a destructor reverses that setup when the object is finished.
- Connecting resource acquisition and release to an object's beginning and end helps explain why constructors and destructors became central to resource management.