OOP Revision Notes (SPPU 2019 – CO210243)
Polymorphism
• Compile-Time Polymorphism (Static): Resolved by the compiler (early binding) using function
overloading or operator overloading 1 . Multiple functions can share the same name with different
parameter lists.
• Run-Time Polymorphism (Dynamic): Achieved using inheritance and virtual functions (late
binding). A base class pointer/reference calls derived-class methods at runtime 2 . This requires
marking the base class method as virtual .
• Function Overloading: Same function name, different signatures. E.g., defining two
add(int,int) and add(double,double) functions allows compile-time selection based on
argument types 1 .
• Function Overriding (Virtual): A derived class redefines a base class virtual method. The call is
resolved at runtime based on actual object type 2 .
• Pure Virtual Functions: Declared with =0 in base class; they make the class abstract (cannot be
instantiated). Derived classes must override them 3 .
• Virtual Destructor: A base class with virtual functions should have a virtual destructor to ensure
derived destructors are called, preventing resource leaks 4 .
Example (compile-time vs runtime):
// Compile-time polymorphism: function overloading
#include <iostream>
using namespace std;
class Calc {
public:
void add(int a, int b) { cout << "Int sum = " << (a + b) << endl; }
void add(double a, double b) { cout << "Double sum = " << (a + b) << endl; }
};
// Run-time polymorphism: virtual function overriding
class Base {
public:
virtual void show() { cout << "Base show\n"; }
};
class Derived : public Base {
public:
void show() override { cout << "Derived show\n"; }
};
int main() {
Calc c;
1
c.add(2, 3); // calls add(int,int)
c.add(2.5, 3.5); // calls add(double,double)
Base *ptr = new Derived();
ptr->show(); // calls Derived::show (runtime binding)
delete ptr;
return 0;
}
Here add() is chosen at compile time, while show() is virtual and resolved at runtime 1 2 .
Operator Overloading
• Purpose: Redefine operators for user-defined types (e.g., + , - , * , << , etc.) to work intuitively
with class objects 5 .
• Syntax: Member operator (e.g. ReturnType operator+(const Type& other) ) or friend/
operator.
• Unary Operators: Operate on one operand (e.g., -a , ++a ). Defined with no arguments (if
member) or one argument (if friend) 6 .
• Binary Operators: Operate on two operands (e.g., a + b ). Defined with one argument (if
member) or two arguments (if friend) 7 .
• Friend Functions: Used when the left operand is not a class object or for symmetric behavior. A
friend operator function takes the class object(s) as parameter(s) 7 .
• Rules: Cannot overload some operators ( :: , . , .* , ?: , sizeof , etc.). Overloaded operators
should mimic the original operator’s behavior logically.
Example (unary, binary, friend):
#include <iostream>
using namespace std;
class Distance {
int feet, inch;
public:
Distance(int f=0, int i=0) : feet(f), inch(i) {}
// Unary operator: decrement both feet and inch
void operator--() { feet--; inch--; }
// Binary operator (member): add two Distance objects
Distance operator+(const Distance &d) {
return Distance(feet + d.feet, inch + d.inch);
}
// Friend operator<< for output
friend ostream& operator<<(ostream &out, const Distance &d) {
out << d.feet << "\'" << d.inch << "\"";
return out;
}
};
2
int main() {
Distance D1(5, 8), D2(3, 11);
--D1; // unary overload
Distance D3 = D1 + D2; // binary overload
cout << "D1 = " << D1 << "\n"; // friend << overload
cout << "D3 = " << D3 << "\n";
return 0;
}
This code overloads unary -- , binary + , and the stream insertion operator << as a friend. Operator
overloading allows Distance objects to be manipulated with familiar syntax 6 8 .
File Handling
• Header & Classes: Include <fstream> to use file streams. ofstream for output (writing to files),
ifstream for input (reading), and fstream for both 9 10 .
• Opening Files: Use constructors or .open() , specifying the filename and optional mode flags.
Common flags: ios::in , ios::out , ios::binary , ios::app , ios::trunc , ios::ate
11 . Flags can be combined with bitwise OR. Default modes: ofstream = out , ifstream =
in , fstream = in|out 11 .
• File Pointers: File streams maintain two pointers: get pointer (position for reading) and put pointer
(for writing). You can query them with tellg() / tellp() and move them with seekg() /
seekp() 12 .
• Checking State: Use is_open() or boolean check on stream to ensure the file opened
successfully 13 . After I/O, always close() the file to flush buffers.
• Streams as I/O: You can use the << operator with an ofstream to write to a file and the >>
operator or getline() with ifstream to read from a file, just as with cin / cout 14 .
Example (writing and reading a text file):
#include <iostream>
#include <fstream>
using namespace std;
int main() {
// Write to file
ofstream fout("example.txt", ios::out);
if (!fout) { cout << "Error opening file for writing\n"; return 1; }
fout << "Line 1\nLine 2\n";
fout.close();
// Read from file
ifstream fin("example.txt", ios::in);
if (!fin.is_open()) { cout << "Error opening file for reading\n"; return
1; }
string line;
3
while (getline(fin, line)) {
cout << line << endl;
}
fin.close();
return 0;
}
This code opens example.txt , writes two lines, then re-opens it for reading and prints its contents. Flags
like ios::in and ios::out control modes 11 . Methods like is_open() or checking the stream
object verify success 13 . Functions getline , seekg , tellg , etc., can be used to navigate file streams
as needed.
Templates
• Function Templates: Define generic functions. A template parameter (e.g., template<typename
T> ) makes the function work with any type without rewriting code 15 . At compile time the compiler
generates type-specific versions.
• Class Templates: Similarly, define classes with type parameters. Useful for container-like classes
( Stack , LinkedList , etc.). Syntax: template<typename T> class MyClass { ... }; 16 .
• Multiple Parameters: Templates can take multiple type parameters, allowing more flexibility. E.g.
template<typename T1, typename T2> class Pair { ... }; handles two types 17 .
• Instantiation: Use <Type> after name when creating objects or calling functions (e.g.
myMax<int>(3,5) ).
• Benefits: Code reusability for different data types with type safety.
Example (function and class templates):
#include <iostream>
using namespace std;
// Function template: returns the greater of two values
template <typename T>
T myMax(T a, T b) {
return (a > b) ? a : b;
}
// Class template with multiple type parameters
template <typename T1, typename T2>
class Pair {
T1 first;
T2 second;
public:
Pair(T1 a, T2 b): first(a), second(b) {}
void print() { cout << first << ", " << second << endl; }
};
4
int main() {
cout << myMax<int>(3, 7) << endl; // prints 7
cout << myMax<double>(4.5, 2.3) << endl; // prints 4.5
Pair<int, double> p(10, 3.14);
p.print(); // prints "10, 3.14"
return 0;
}
The myMax template works for int or double based on usage 15 . The Pair class template holds an
int and a double in one object 17 , demonstrating templates with multiple type parameters. Templates
generate concrete code at compile time for the types used.
Exception Handling
• Basics: Use try { ... } to enclose code that may throw an exception, and catch blocks to
handle specific exceptions 18 . Use the throw keyword to raise an exception (of any type) when an
error is detected.
• Example Types: Can throw built-in types (e.g., int ), standard exceptions (e.g., runtime_error ,
logic_error ), or user-defined class-type exceptions 19 20 .
• Multiple Catches: You can have multiple catch blocks after one try to handle different
exception types. A catch-all catch(...) can catch any exception.
• Rethrowing: Inside a catch block, you can rethrow the same exception using throw; , passing it
up to the next handler 21 . This is useful for cleanup or logging at intermediate levels.
• Class-Type Exceptions: By deriving from std::exception , a class can be thrown and caught
polymorphically. Override the what() method to provide an error message 20 .
Example (try-catch, throw, rethrow, custom exception):
#include <iostream>
#include <stdexcept>
using namespace std;
class MyException : public exception {
public:
const char* what() const noexcept override {
return "My exception occurred";
}
};
int main() {
try {
int a = 10, b = 0;
if (b == 0) throw runtime_error("Divide by zero"); // standard exception
int c = a / b;
}
5
catch (const runtime_error& e) {
cout << "Runtime error: " << e.what() << endl;
// rethrow to outer handler
throw;
}
catch (const exception& e) {
cout << "Standard exception: " << e.what() << endl;
}
try {
throw MyException(); // throwing a class-type exception
}
catch (const exception& e) {
cout << "Caught: " << e.what() << endl;
}
return 0;
}
In this code, dividing by zero throws a runtime_error , caught by the first catch and rethrown 21 . The
custom MyException (derived from std::exception ) is thrown and caught, demonstrating a class-
type exception 20 . Each catch handles the exception gracefully instead of crashing.
Standard Template Library (STL)
• Containers: Predefined classes for common data structures. Sequence containers (e.g., vector ,
list , deque ) store ordered data. Associative containers (e.g., set , map ) store sorted data by
key. Container adapters ( stack , queue , priority_queue ) provide restricted interfaces. For
example, std::vector is a dynamic array (sequence container) 22 .
• Iterators: Objects that enable traversing containers (like generalized pointers). Iterator categories:
input/output, forward, bidirectional, random-access. For example, vector<int>::iterator
supports random access. Use begin() , end() to obtain iterators.
• Algorithms: Functions in <algorithm> operate on ranges via iterators (e.g., sort , find ,
copy ). Most algorithms use iterators and work with any container supporting them.
• Example – sort(): std::sort(v.begin(), v.end()) sorts the vector in ascending order.
Internally it uses introsort (average O(n log n)) 23 .
• Example – map: std::map<Key,Value> is a sorted associative container. It stores key-value pairs
sorted by key. Iterate with begin()/end() . When iterating a map, elements appear in ascending
key order 24 .
Example (vector sort and map iteration):
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
6
int main() {
// Sort a vector
vector<int> v = {4, 1, 3, 2};
sort(v.begin(), v.end()); // uses <algorithm>
cout << "Sorted vector: ";
for(int x : v) cout << x << " ";
cout << endl;
// Use a map
map<int,string> mp;
mp[2] = "Two"; mp[1] = "One"; mp[3] = "Three";
cout << "Map contents:\n";
for(auto it = mp.begin(); it != mp.end(); ++it) {
cout << it->first << " => " << it->second << "\n";
}
return 0;
}
This sorts the vector (achieving average O(n log n) time 23 ) and then stores key-value pairs in a map.
Iterating the map with begin() / end() outputs entries in sorted key order 24 .
Command-Line Arguments
• Signature: In C++, main can accept arguments: int main(int argc, char *argv[]) . Here
argc is the argument count and argv is an array of C-strings containing each argument 25 .
• Values: argv[0] is the program name. Subsequent indices argv[1]...argv[argc-1] are the
arguments passed.
• Usage: Allows programs to receive input parameters from the command line. Commonly parsed into
integer or other types as needed.
Example:
#include <iostream>
using namespace std;
int main(int argc, char* argv[]) {
cout << "Program name: " << argv[0] << "\n";
cout << "Number of args: " << argc << "\n";
for(int i = 1; i < argc; ++i) {
cout << "Arg " << i << ": " << argv[i] << "\n";
}
return 0;
}
If run with ./prog one two , this prints the program name and the two arguments. argc counts all
arguments including the program name, and argv holds them 25 .
7
1 2 C++ Polymorphism | GeeksforGeeks
https://www.geeksforgeeks.org/cpp-polymorphism/
3 Pure Virtual Functions and Abstract Classes in C++ | GeeksforGeeks
https://www.geeksforgeeks.org/pure-virtual-functions-and-abstract-classes/
4 Virtual Destructor | GeeksforGeeks
https://www.geeksforgeeks.org/virtual-destructor/
5 6 7 8 Types of Operator Overloading in C++ | GeeksforGeeks
https://www.geeksforgeeks.org/types-of-operator-overloading-in-cpp/
9 11 12 13 14 cplusplus.com
https://cplusplus.com/doc/tutorial/files/
10 C++ Files
https://www.w3schools.com/cpp/cpp_files.asp
15 16 17 Templates in C++ | GeeksforGeeks
https://www.geeksforgeeks.org/templates-cpp/
18 19 Exception Handling in C++ | GeeksforGeeks
https://www.geeksforgeeks.org/exception-handling-c/
20 cplusplus.com
https://cplusplus.com/doc/tutorial/exceptions/
21 Rethrowing an Exception in C++ | GeeksforGeeks
https://www.geeksforgeeks.org/rethrowing-an-exception-in-cpp/
22 cplusplus.com
https://cplusplus.com/reference/vector/vector/
23 sort() in C++ STL | GeeksforGeeks
https://www.geeksforgeeks.org/sort-c-stl/
24 Map in C++ STL | GeeksforGeeks
https://www.geeksforgeeks.org/map-associative-containers-the-c-standard-template-library-stl/
25 Command Line Arguments in C++ | GeeksforGeeks
https://www.geeksforgeeks.org/command-line-arguments-in-cpp/