Lesson 1
Building Classes in C++ Introduction
Welcome to
Building Classes in C++, the second course in the
C++ for C Programmers series.
This course teaches you the basics of working with classes and objects in C++.
It introduces you to one important aspect of object-oriented programming (OOP) which is encapsulation and prepares you to continue exploring OOP techniques and concepts.
After completing this course, you will be able to write C++ programs that:
- Use the
class
construct to define Abstract Data Types (ADTs) and implement encapsulation of data and behavior
- Write member functions that act on member data
- Use constructor and destructor member functions to manage class-defined objects
- Implement useful dynamic data structures such as a dynamically allocated stack, a bounds-checking array, and a singly linked list
- Use an efficient object disposal scheme
Visual C++ provides two ways of building a C/C++ program. The easiest (and most common) way is to build within the Visual C++ development environment. The other way is to build from a command prompt using command-line tools. In either case, you can create your source files using the Visual C++ source editor or a third-party editor of your choice. If your program uses a makefile rather than a .vcxproj file, you can still build it in the development environment as an external project.
Main Objectives a developer should focus on
When building classes in C++, the main objectives a developer should focus on revolve around implementing core Object-Oriented Programming (OOP) principles. These principles guide the design of robust, reusable, and maintainable code. Here are the key objectives:
-
Encapsulation
The primary goal when building a class is to ensure encapsulation, which is the bundling of data (attributes) and methods (functions) that operate on that data into a single unit. To achieve encapsulation:
- Use access specifiers (
private
, protected
, public
) to restrict direct access to the class's internal state and expose only what is necessary.
- Provide controlled access through getter and setter methods to manipulate private data while maintaining constraints and validations.
- Encapsulation protects the integrity of an object by preventing external interference with its internal workings.
Example:
class Person {
private:
std::string name; // Private attribute
int age;
public:
// Constructor
Person(const std::string& personName, int personAge) : name(personName), age(personAge) {}
// Getter for name
std::string getName() const {
return name;
}
// Setter for name
void setName(const std::string& newName) {
name = newName;
}
// Method to display details
void display() const {
std::cout << "Name: " << name << ", Age: " << age << std::endl;
}
};
-
Reusability and Modularity
Another important objective is designing classes to promote code reuse and modularity:
- Ensure the class is single-responsibility, meaning it should only perform tasks specific to its purpose.
- Focus on creating general-purpose classes that can be reused across different parts of the program.
- Group related functionalities within the same class, and keep unrelated functionalities in separate classes.
Modularity enables easier debugging, testing, and maintenance of code.
-
Data Abstraction
A developer should emphasize data abstraction, which involves exposing only essential features and hiding unnecessary details. The goal is to:
- Provide a clean and simple interface (e.g., public methods) to interact with the class.
- Hide implementation details so users of the class don’t need to understand its inner workings.
This makes the class easier to use and less prone to errors.
-
Inheritance and Polymorphism (Optional but Useful)
When designing classes, consider inheritance and polymorphism to extend functionality:
- Inheritance allows a new class to derive from an existing one, promoting code reuse.
- Polymorphism enables methods in derived classes to override base class methods, supporting dynamic behavior at runtime.
These features are especially important when designing frameworks or systems with interchangeable components.
Example:
class Animal {
public:
virtual void sound() const {
std::cout << "Animal makes a sound" << std::endl;
}
};
class Dog : public Animal {
public:
void sound() const override {
std::cout << "Dog barks" << std::endl;
}
};
-
Error Handling and Robustness
When building classes, ensure they handle errors gracefully:
- Implement proper validation within setter methods to prevent invalid states.
- Use constructors to initialize attributes, ensuring objects are always in a valid state after creation.
- Employ exceptions for handling critical errors, such as invalid inputs or failed operations.
-
Performance and Resource Management
Efficient resource management is crucial, especially in C++:
- Use destructors to release dynamically allocated resources and avoid memory leaks.
- Leverage RAII (Resource Acquisition Is Initialization) principles to tie resource lifetimes to object lifetimes.
- Implement move semantics and use smart pointers where applicable to optimize memory usage and ownership management.
By focusing on these objectives, a developer can design C++ classes that embody OOP principles and serve as the foundation for scalable and maintainable applications.
Understand the essentials of object-oriented programming in C++
This module reviews object-oriented programming in C++. It assumes the reader has prior experience programming in C++ or another language and is, therefore, familiar with control statements for selection and repetition, basic data types, arrays, and functions.
If your first course was in C++, you can skim this chapter for review or just use it as a reference as needed. However, you should read it more carefully if your C++ course did not emphasize object-oriented design.
If your first course followed an object-oriented approach but was in another language, you should concentrate on the differences between C++ syntax and that of the language that you know. If you have programmed only in a language that was not
object-oriented, you will need to concentrate on aspects of object-oriented programming and classes as well as C++ syntax.
We begin the module with an introduction to the C++ environment and the runtime system. Control structures and statements are then discussed, followed by a discussion of functions. Next we cover the basic data types of C++, called primitive data types. Then we introduce classes and objects. Because C++ uses pointers to reference objects, we discuss how to declare and use pointer variables.
The C++ standard library provides a rich collection of classes that simplify programming in C++. The first C++ class that we cover is the string class.
The string class provides several functions and an operator + (concatenation) that process sequences of characters (strings). We also review arrays in C++. We cover both one- and two-dimensional arrays and C-strings, which are arrays of characters.
Finally we discuss input/output. We also show how to use streams and the console for input/output and how to write functions that let us use the stream input/output operations on objects.