C++ and Object-Oriented Programming
Pure Virtual Functions and Abstract Classes; Templates; Exception Handling
C-CAT
Pure Virtual Functions and Abstract Classes
Pure Virtual Function
A pure virtual function has no implementation — derived classes MUST override it.
class AbstractShape {
public:
// Pure virtual function — no implementation
virtual double area() = 0; // = 0 makes it pure virtual
virtual double perimeter() = 0; // pure virtual
// Non-virtual function — shared implementation
void display() {
cout << "Area: " << area()
<< ", Perimeter: " << perimeter() << endl;
}
virtual ~AbstractShape() {}
};
Abstract class: A class with at least one pure virtual function.
- Cannot be instantiated — you cannot create objects of abstract class
- Can have pointers and references to abstract class type
- Derived classes must override ALL pure virtual functions (or be abstract too)
// AbstractShape s; // ERROR: cannot create object of abstract class
AbstractShape *s = new Circle(5.0); // OK: pointer to abstract class
s->display(); // Uses Circle's area() and perimeter()
Interface Pattern
// Interface: pure abstract class (all functions pure virtual)
class Printable {
public:
virtual void print() = 0;
virtual ~Printable() {}
};
class Serializable {
public:
virtual string serialize() = 0;
virtual ~Serializable()
{}
};
// Implement multiple interfaces
class Document : public Printable, public Serializable {
private:
string content;
public:
Document(string c) : content(c) {}
void print() override { cout << content << endl; }
string serialize() override { return "{\"content\":\"" + content + "\"}"; }
};
Templates
What are Templates?
Templates allow writing generic code that works with any data type.
Function Templates
// Generic max function — works for any comparable type
template <typename T>
T maxOf(T a, T b) {
return (a > b) ? a : b;
}
int main() {
cout << maxOf(3, 7) << endl; // 7 (int comparison)
cout << maxOf(3.14, 2.71) << endl; // 3.14 (double comparison)
cout << maxOf('a', 'z') << endl; // z (char comparison)
cout << maxOf(string("apple"), string("banana")) << endl; // banana
return 0;
}
Class Templates
template <typename T>
class Stack {
private:
T arr[100];
int top;
public:
Stack() : top(-1) {}
void push(T value) {
if (top == 99) { cout << "Stack overflow!\n"; return; }
arr[++top] = value;
}
T pop() {
if (top == -1) { throw runtime_error("Stack empty"); }
return arr[top--];
}
T peek() { return arr[top]; }
bool isEmpty() { return top == -1; }
};
int main() {
Stack<int> intStack;
intStack.push(10);
intStack.push(20);
cout
<< intStack.pop() << endl; // 20
Stack<string> strStack;
strStack.push("Hello");
strStack.push("World");
cout << strStack.pop() << endl; // World
return 0;
}
Multiple Template Parameters
template <typename Key, typename Value>
class Dictionary {
// ...
};
Dictionary<string, int> wordCount;
Dictionary<int, string> idLookup;
Exception Handling
What is Exception Handling?
Exception handling manages runtime errors gracefully without crashing the program.
Three keywords:
try— block of code that might throw an exceptionthrow— throws an exceptioncatch— handles the exception
#include <iostream>
#include <stdexcept>
using namespace std;
double divide(double a, double b) {
if (b == 0) {
throw runtime_error("Division
by zero!"); // throw exception
}
return a / b;
}
int main() {
try {
cout << divide(10, 2) << endl; // 5.0 — works fine
cout << divide(10, 0) << endl; // throws exception!
}
catch (runtime_error &e) {
cout << "Error: " << e.what() << endl; // Error: Division by zero!
}
catch (exception &e) {
cout << "General error: " << e.what() << endl;
}
catch (...) {
cout << "Unknown exception caught\n";
}
cout << "Program continues after exception\n";
return 0;
}
Custom Exceptions
class InsufficientFundsException : public exception {
private:
double amount;
public:
InsufficientFundsException(double a) : amount(a) {}
const char* what() const noexcept override {
return "Insufficient funds in account";
}
double getAmount() { return amount; }
};
class BankAccount {
private:
double balance;
public:
BankAccount(double initial) :
balance(initial) {}
void withdraw(double amount) {
if (amount > balance) {
throw InsufficientFundsException(amount - balance);
}
balance -= amount;
}
};
int main() {
BankAccount acc(1000.0);
try {
acc.withdraw(500.0); // OK
acc.withdraw(600.0); // throws InsufficientFundsException
}
catch (InsufficientFundsException &e) {
cout << e.what() << " (short by " << e.getAmount() << ")\n";
}
return 0;
}
Exception Hierarchy
std::exception
├── std::logic_error
│ ├── std::invalid_argument
│ ├── std::out_of_range
│ └── std::length_error
└── std::runtime_error
├── std::overflow_error
├── std::underflow_error
└── std::range_error
Continue learning
Related notes
Definition of AI; Need of AI
Artificial Intelligence
Introduction to Data Engineering; Big Data — The 5 V's; Types of Data
Big Data and Data Engineering
Introduction to C Programming; C Program Structure; Data Types and Variables
C Programming
What Is a Computer?; Machine Cycle: Fetch–Decode–Execute; CPU Organization
Computer Architecture
Put this topic into timed practice
Open mock tests when you want full-exam pacing, or keep drilling in practice mode.