Topic 212 Key Rules
Module 2: Basic Concepts of OOP
# Object-Oriented Programming (OOP) - Master Class Reference
A detailed, academic, and exam-oriented study guide focusing on Object-Oriented Programming principles, implementation differences in C++ and Java, and critical university-level pitfalls.
---
## 1. Core Pillars of OOP
### A. Encapsulation (Data Hiding)
- **Concept**: Bundling data attributes and member functions that manipulate them into a single logical unit (a Class).
- **Purpose**: Achieving data hiding to protect an object's internal state from unauthorized direct access or modification.
- **Implementation**: Done via access specifiers (`private`, `protected`, `public`). External classes access private variables only through controlled public getters and setters.
### B. Abstraction (Complexity Hiding)
- **Concept**: Hiding internal implementation and showing only essential features to the outside world.
- **Purpose**: Reducing complexity and decoupling implementation from interface.
- **Implementation**: Done using abstract classes (in C++/Java) and interfaces (in Java). For example, a user knows how to push the accelerator pedal of a car without needing to understand how fuel injection is managed.
### C. Inheritance (Code Reuse & Hierarchy)
- **Concept**: The mechanism where a derived subclass acquires attributes and behaviors of a parent base class.
- **Types**:
- **Single**: Class B extends Class A.
- **Multilevel**: Class C extends Class B, which extends Class A.
- **Hierarchical**: Class B and Class C both extend Class A.
- **Multiple**: Class C extends both Class A and Class B (supported in C++; not supported in Java for classes).
- **Hybrid**: A combination of multiple and hierarchical inheritance.
### D. Polymorphism (Multiple Forms)
- **Compile-Time (Static) Polymorphism**: Resolved during compilation.
- **Function Overloading**: Multiple functions with the same name but different signatures (parameter types or numbers) within the same scope.
- **Operator Overloading**: Overloading operators (like `+`, `*`) to perform custom operations on user-defined types (supported in C++; not supported in Java to keep syntax clean).
- **Run-Time (Dynamic) Polymorphism**: Resolved at runtime based on the actual object instance.
- **Method Overriding**: A derived class provides a specific implementation of a method already declared in its base class with the exact same name, return type, and signature.
- **Dynamic Dispatch**: In C++, enabled via the `virtual` keyword, `VTable` (Virtual Table), and `VPtr` (Virtual Pointer). In Java, non-static, non-private methods are virtual by default.
---
## 2. C++ vs Java OOP: Deep Dive Comparison
| Feature | C++ | Java |
|---|---|---|
| **Compilation & Execution** | Compiled directly to native machine code. | Compiled to bytecode; executed inside JVM. |
| **Memory Management** | Manual allocation (`new`) and deallocation (`delete`). Destructors clean up resources. | Automatic Garbage Collection (GC) sweeps unreachable objects. No destructors. |
| **Pointers** | Explicit support. Memory addresses can be manipulated directly. | No explicit pointer arithmetic. Variables hold references to objects on the heap. |
| **Virtual Methods** | Must be declared explicitly using the `virtual` keyword. | All non-static, non-private, non-final methods are virtual by default. |
| **Multiple Inheritance** | Supported directly for classes. | Not supported for classes (causes Diamond Problem). Supported for interfaces. |
| **Operator Overloading** | Supported. | Not supported (except for string concatenation `+`). |
| **Access Specifiers** | `public`, `protected`, `private`. | `public`, `protected`, `private`, and default (package-private). |
| **Base Class Initialization** | Done via Constructor Initialization List: `Derived() : Base() {}`. | Done via explicit/implicit `super()` call inside constructor. |
---
## 3. Famous University-Level Pitfalls & Concept Deep Dives
### Pitfall A: The Multiple Inheritance "Diamond Problem"
- **The Issue**: Suppose Class A has a method `display()`. Class B and Class C inherit from Class A and override `display()`. Class D inherits from both Class B and Class C (multiple inheritance). When Class D calls `display()`, which parent version should be invoked? This creates ambiguity, known as the Diamond Problem.
- **C++ Resolution**: C++ resolves this using **Virtual Inheritance**. Declaring base classes as virtual (e.g., `class B : virtual public A` and `class C : virtual public A`) ensures that Class D inherits only **one** instance of Class A's members.
- **Why Java Doesn't Support Multiple Class Inheritance**: To avoid the ambiguity, complexity, and compiler overhead of virtual inheritance tables. Instead, Java allows a class to implement multiple **Interfaces**, which do not hold state. In Java 8+, interfaces can have `default` methods; if a naming conflict occurs, Java forces the implementing class to override and explicitly resolve the method to call (e.g., `InterfaceA.super.method()`).
- **Clarification**: Java **does** support **Multilevel** inheritance (A -> B -> C). The restriction is strictly on multiple inheritance of classes.
### Pitfall B: The Empty Class Size Paradox
- **C++**: The size of an empty class in C++ is **1 byte** (never 0). This is to ensure that different object instances of the empty class have distinct, unique memory addresses (e.g., `&obj1 != &obj2`).
- **Java**: An empty object in Java typically takes **8 to 16 bytes** depending on the JVM architecture (32-bit vs 64-bit). This memory is consumed by the **Object Header**, which stores metadata like the Mark Word (locking, GC age, hashcode) and the Klass Word (pointer to class metadata).
### Pitfall C: Object Slicing in C++
- **The Issue**: Object slicing occurs in C++ when a derived class object is assigned to a base class object **by value** (not by reference or pointer).
- **Result**: The extra attributes and behaviors of the derived class are "sliced off" because the base class object cannot accommodate them.
- **Example**: `Base b = DerivedObj;` slices the object. `Base& b = DerivedObj;` or `Base* b = &DerivedObj;` preserves polymorphic behavior.
- **Java Equivalence**: Java does not suffer from object slicing because Java object variables are references, not values. Assigning a subclass reference to a parent class variable only performs upcasting, leaving the underlying object intact.
### Pitfall D: Virtual Destructors & Memory Leaks in C++
- **The Issue**: If a base class pointer points to a derived class object (e.g., `Base* ptr = new Derived();`) and we execute `delete ptr;`, only the base class destructor is invoked if the destructor is not declared virtual.
- **Result**: The derived class destructor is skipped, leading to memory leaks if the derived class allocated dynamic heap memory (e.g., arrays, file streams).
- **Resolution**: Always declare the base class destructor as `virtual`: `virtual ~Base() {}`. This ensures the derived class destructor runs first, followed by the base class destructor.
- **Java Equivalence**: Java does not have destructors or manual deletion. The Garbage Collector handles heap deallocation, making virtual destructors unnecessary.
### Pitfall E: Can Constructors or Destructors Be Virtual?
- **Constructor**: Can **never** be virtual in either C++ or Java. A constructor's purpose is to build an object of an exact type, which requires compile-time binding. Virtual dispatch requires a VPtr, which is only set up *after* the constructor runs.
- **Destructor**: Can and **must** be virtual in C++ base classes when polymorphism is applied. Destructors do not exist in Java.
---
## 4. One-Liner Quick-Fire Q&As (High-Yield Interview & Exam FAQ)
1. **Why does Java not support multiple class inheritance?**
To eliminate the compiler complexity and method-resolution ambiguity associated with the Diamond Problem.
2. **What is the size of an empty class in C++?**
1 byte, to ensure that every object instance of the class has a unique memory address.
3. **What is the primary cause of object slicing in C++?**
Assigning a derived class object to a base class object by value instead of by reference or pointer.
4. **Why are base class destructors declared virtual in C++?**
To ensure that the derived class destructor is called and derived members are cleaned up when deleting via a base class pointer.
5. **Why can constructors never be virtual?**
Constructors must create an object of an exact type, which requires static binding, and the virtual table pointer (VPtr) is not yet initialized.
6. **In Java, which methods are bound statically at compile time?**
Methods marked as `private`, `static`, or `final` are bound statically (Compile-Time binding) because they cannot be overridden.
7. **What is the difference between Aggregation and Composition?**
Aggregation represents a weak "has-a" relationship with independent lifetimes, while Composition represents a strong "part-of" relationship where child lifetimes are tied to the parent.
8. **How does C++ resolve the Diamond Problem?**
By using virtual inheritance (e.g., `class B : virtual public A`) to ensure only a single shared instance of the common grandparent class is created.
9. **Can an abstract class be instantiated directly?**
No, abstract classes are incomplete blueprints and cannot be instantiated; they can only be used as base classes for inheritance.
10. **What is the purpose of a Copy Constructor?**
To initialize a new object as an exact copy of an existing object of the same class.