Object-Oriented Programming
Lesson outline
Introduction to OOP
Object-Oriented Programming (OOP) organizes software around data (objects) rather than functions and logic. C++ fully supports OOP as one of its paradigms.
The four main pillars of OOP are:
- Encapsulation: Bundling data and the methods that operate on it
- Abstraction: Hiding complex implementation details behind simpler interfaces
- Inheritance: Creating new classes based on existing ones
- Polymorphism: Using a single interface for multiple implementations
Classes and Objects
A class is a blueprint; an object is an instance of a class.
Classes usually contain:
- Attributes (data members/variables)
- Methods (member functions)
- Constructors/Destructors (special member functions)
Access Modifiers
Access specifiers control visibility of class members:
- public: Accessible from anywhere
- private: Accessible only inside the class (default for classes)
- protected: Accessible inside the class and derived classes
Note: For struct, the default member access is public. Also, class Derived : Base defaults to private inheritance if class is used without an access specifier; struct Derived : Base defaults to public.
Constructors and Destructors
Constructors are special functions called when an object is created. Destructors are called when the object is destroyed.
Types of constructors:
- Default constructor (no parameters)
- Parameterized constructor
- Copy constructor
- Move constructor (C++11 and later)
Prefer member-initializer lists and consider defaulting or deleting special members explicitly when appropriate.
Class Methods
Methods may be defined inside or outside the class definition (using the scope resolution operator).
Special categories of methods:
- Const methods: Do not modify object state
- Static methods: Belong to the class rather than an object
- Friend functions: Access private members from outside
Inheritance
Inheritance lets new classes reuse and extend existing ones.
Types: single, multiple, multilevel, hierarchical, hybrid
Polymorphism
Polymorphism allows treating different derived objects as base objects.
Types:
- Compile-time (function/operator overloading)
- Runtime (virtual functions and overriding)
Avoid object slicing: store polymorphic objects via pointers/references, not by value.
Abstract Classes and Interfaces
An abstract class has at least one pure virtual function and cannot be instantiated directly.
C++ does not have a separate interface construct, but interface-like behavior is achieved with abstract classes containing only pure virtual functions.
Operator Overloading
C++ lets you redefine operators for user-defined types. Commonly overloaded operators include arithmetic, comparison, I/O, and subscripting.
Friend Classes and Functions
Friend functions and classes can access private and protected members of another class. Use this feature carefully.
Static Members
Static members belong to the class rather than objects. Only one copy exists regardless of how many objects are created.
Composition vs Inheritance
Composition (has-a relationship) is often preferable to inheritance (is-a relationship).
Guidelines:
- Use inheritance for clear specialization
- Use composition for flexible code reuse
- Favor composition when unsure to reduce coupling
Override/Final and Explicit
Use override to ensure you're actually overriding a virtual function. Use final to prevent further overriding.
Mark single-argument constructors explicit to avoid unintended implicit conversions.
Best Practices
| Practice | Description | Example |
|---|---|---|
| Rule of Three/Five/Zero | If you implement one of destructor, copy constructor, or copy assignment, you likely need all three (plus move in C++11+). Prefer the Rule of Zero when possible (let the compiler generate them). | struct ResourceHolder { /* use std::unique_ptr, default special members */ }; |
| RAII | Tie resource management to object lifetime. | Use smart pointers like std::unique_ptr or std::shared_ptr. |
| SOLID Principles | Design classes with single responsibility and clear abstractions. | Keep each class focused on one task. |
| PIMPL Idiom | Hide implementation details in a separate class. | Use a private pointer to the implementation class. |
Practical Example: Banking System
A simple banking system showing OOP concepts in practice (using RAII with smart pointers):