C++98corebeginner
Abstract Classes
C++98 · The Foundation · Compiler flag: -std=c++98
Explanation
Classes with pure virtual functions that cannot be instantiated.
Real-World Scenario
A `Vehicle` base class ensuring all vehicles define `move`.
Quick Snippet
snippet.cpp
class Vehicle { virtual void move() = 0; };Full Example
abstract_classes.cpp
// CodeNebula - C++98 Example: Abstract Classes
// Compile: g++ -std=c++98 -Wall -Wextra -o example abstract_classes.cpp
//
// This example demonstrates:
// - Abstract base classes as design contracts (interfaces)
// - Multiple concrete classes implementing the same abstract interface
// - Factory pattern using abstract base
// - Template Method pattern: base defines algorithm skeleton,
// derived fills in steps
#include <iostream>
#include <cstring>
// ============================================================
// 1. Abstract Interface: Database
// ============================================================
class Database {
public:
virtual ~Database() {}
// Pure virtual interface
virtual void connect(const char* connectionStr) = 0;
virtual void disconnect() = 0;
virtual void execute(const char* query) = 0;
virtual const char* getName() const = 0;
};
// Concrete: MySQLDatabase
class MySQLDatabase : public Database {
private:
bool connected;
public:
MySQLDatabase() : connected(false) {}
void connect(const char* connectionStr) {
std::cout << " [MySQL] Connecting to: " << connectionStr << std::endl;
connected = true;
}
void disconnect() {
std::cout << " [MySQL] Disconnected" << std::endl;
connected = false;
}
void execute(const char* query) {
if (!connected) {
std::cout << " [MySQL] ERROR: not connected!" << std::endl;
return;
}
std::cout << " [MySQL] Executing: " << query << std::endl;
}
const char* getName() const { return "MySQL"; }
};
// Concrete: PostgresDatabase
class PostgresDatabase : public Database {
private:
bool connected;
public:
PostgresDatabase() : connected(false) {}
void connect(const char* connectionStr) {
std::cout << " [Postgres] Connecting to: " << connectionStr << std::endl;
connected = true;
}
void disconnect() {
std::cout << " [Postgres] Disconnected" << std::endl;
connected = false;
}
void execute(const char* query) {
if (!connected) {
std::cout << " [Postgres] ERROR: not connected!" << std::endl;
return;
}
std::cout << " [Postgres] Executing: " << query << std::endl;
}
const char* getName() const { return "PostgreSQL"; }
};
// Function that works with ANY Database -- client code is database-agnostic
void runMigration(Database& db, const char* connStr) {
std::cout << " Running migration on " << db.getName() << ":" << std::endl;
db.connect(connStr);
db.execute("CREATE TABLE users (id INT, name TEXT)");
db.execute("INSERT INTO users VALUES (1, 'Alice')");
db.disconnect();
}
// ============================================================
// 2. Template Method Pattern
// Base defines the algorithm, derived provides the steps
// ============================================================
class Report {
public:
virtual ~Report() {}
// Template method: defines the skeleton (non-virtual, or could be)
void generate() const {
std::cout << " === " << title() << " ===" << std::endl;
header();
body();
footer();
std::cout << " === End of Report ===" << std::endl;
}
protected:
// Steps to be overridden by derived classes
virtual const char* title() const = 0;
virtual void header() const = 0;
virtual void body() const = 0;
// Default footer (can be overridden, but not required)
virtual void footer() const {
std::cout << " Footer: Generated by ReportEngine v1.0" << std::endl;
}
};
class SalesReport : public Report {
protected:
const char* title() const { return "Sales Report Q4"; }
void header() const {
std::cout << " Date: 2024-12-15 | Department: Sales" << std::endl;
}
void body() const {
std::cout << " Total Revenue: $125,000" << std::endl;
std::cout << " Units Sold: 500" << std::endl;
std::cout << " Top Product: Widget Pro" << std::endl;
}
};
class InventoryReport : public Report {
protected:
const char* title() const { return "Inventory Report"; }
void header() const {
std::cout << " Warehouse: Central | Date: 2024-12-15" << std::endl;
}
void body() const {
std::cout << " Items in stock: 1,234" << std::endl;
std::cout << " Low stock items: 12" << std::endl;
}
// Override footer with custom version
void footer() const {
std::cout << " Footer: Inventory system auto-generated" << std::endl;
}
};
// ============================================================
// 3. Simple Factory using abstract base
// ============================================================
Database* createDatabase(const char* type) {
if (std::strcmp(type, "mysql") == 0) {
return new MySQLDatabase();
}
if (std::strcmp(type, "postgres") == 0) {
return new PostgresDatabase();
}
std::cout << " Unknown database type: " << type << std::endl;
return NULL;
}
int main() {
std::cout << "========================================" << std::endl;
std::cout << "1. ABSTRACT INTERFACE (Database)" << std::endl;
std::cout << "========================================" << std::endl;
{
// Database db; // COMPILE ERROR: cannot instantiate abstract class
MySQLDatabase mysql;
PostgresDatabase pg;
// Same function works with both -- polymorphism via abstract base
runMigration(mysql, "localhost:3306/mydb");
std::cout << std::endl;
runMigration(pg, "localhost:5432/mydb");
}
std::cout << "\n========================================" << std::endl;
std::cout << "2. FACTORY PATTERN WITH ABSTRACT BASE" << std::endl;
std::cout << "========================================" << std::endl;
{
const char* types[] = { "mysql", "postgres", "oracle" };
const int count = 3;
for (int i = 0; i < count; ++i) {
std::cout << " Creating database: " << types[i] << std::endl;
Database* db = createDatabase(types[i]);
if (db != NULL) {
db->connect("factory-connection");
db->execute("SELECT 1");
db->disconnect();
delete db;
}
std::cout << std::endl;
}
}
std::cout << "========================================" << std::endl;
std::cout << "3. TEMPLATE METHOD PATTERN" << std::endl;
std::cout << "========================================" << std::endl;
{
SalesReport sales;
InventoryReport inventory;
// Same generate() algorithm, different content
sales.generate();
std::cout << std::endl;
inventory.generate();
}
std::cout << "\n========================================" << std::endl;
std::cout << "4. ABSTRACT CLASS AS CONTRACT" << std::endl;
std::cout << "========================================" << std::endl;
std::cout << " An abstract class defines a CONTRACT:" << std::endl;
std::cout << " - What methods must every implementation provide?" << std::endl;
std::cout << " - Client code depends on the abstract type, not concrete" << std::endl;
std::cout << " - New implementations can be added without changing clients" << std::endl;
std::cout << " - The abstract class can provide shared default behaviour" << std::endl;
std::cout << " (unlike a pure interface with only = 0 methods)" << std::endl;
return 0;
}
// Expected output:
// ========================================
// 1. ABSTRACT INTERFACE (Database)
// ========================================
// Running migration on MySQL:
// [MySQL] Connecting to: localhost:3306/mydb
// [MySQL] Executing: CREATE TABLE users (id INT, name TEXT)
// [MySQL] Executing: INSERT INTO users VALUES (1, 'Alice')
// [MySQL] Disconnected
//
// Running migration on PostgreSQL:
// [Postgres] Connecting to: localhost:5432/mydb
// [Postgres] Executing: CREATE TABLE users (id INT, name TEXT)
// [Postgres] Executing: INSERT INTO users VALUES (1, 'Alice')
// [Postgres] Disconnected
//
// ========================================
// 2. FACTORY PATTERN WITH ABSTRACT BASE
// ========================================
// Creating database: mysql
// [MySQL] Connecting to: factory-connection
// [MySQL] Executing: SELECT 1
// [MySQL] Disconnected
//
// Creating database: postgres
// [Postgres] Connecting to: factory-connection
// [Postgres] Executing: SELECT 1
// [Postgres] Disconnected
//
// Creating database: oracle
// Unknown database type: oracle
//
// ========================================
// 3. TEMPLATE METHOD PATTERN
// ========================================
// === Sales Report Q4 ===
// Date: 2024-12-15 | Department: Sales
// Total Revenue: $125,000
// Units Sold: 500
// Top Product: Widget Pro
// Footer: Generated by ReportEngine v1.0
// === End of Report ===
//
// === Inventory Report ===
// Warehouse: Central | Date: 2024-12-15
// Items in stock: 1,234
// Low stock items: 12
// Footer: Inventory system auto-generated
// === End of Report ===
//
// ========================================
// 4. ABSTRACT CLASS AS CONTRACT
// ========================================
// ...summary...
Run command
g++ -std=c++98 -Wall -Wextra -o example abstract_classes.cpp