Practice Questions — Abstract Classes, Pure Virtual Functions, and Interfaces
← Back to NotesTopic-Specific Questions
Question 1
Easy
What happens when you try to compile this code?
class Animal {
public:
virtual void sound() = 0;
virtual ~Animal() {}
};
int main() {
Animal a;
return 0;
}Animal has a pure virtual function. Can you create an object of it?
Compilation error: cannot declare variable 'a' to be of abstract type 'Animal'.
Question 2
Easy
What is the output?
#include <iostream>
using namespace std;
class Shape {
public:
virtual double area() const = 0;
virtual ~Shape() {}
};
class Square : public Shape {
double side;
public:
Square(double s) : side(s) {}
double area() const override { return side * side; }
};
int main() {
Shape* s = new Square(5);
cout << s->area() << endl;
delete s;
return 0;
}Square implements area(), so it is concrete. The pointer type is Shape*.
25Question 3
Easy
Does this code compile?
class Printable {
public:
virtual void print() const = 0;
virtual ~Printable() {}
};
class Report : public Printable {
// print() not implemented
};
int main() {
Report r;
return 0;
}Report does not implement print(). Is it still abstract?
Compilation error: cannot declare variable 'r' to be of abstract type 'Report'.
Question 4
Easy
What is the output?
#include <iostream>
using namespace std;
class Vehicle {
public:
virtual void start() = 0;
void honk() { cout << "Beep!" << endl; }
virtual ~Vehicle() {}
};
class Car : public Vehicle {
public:
void start() override { cout << "Car started" << endl; }
};
int main() {
Car c;
c.start();
c.honk();
return 0;
}honk() is a non-virtual function in the abstract class. Car inherits it.
Car startedBeep!Question 5
Easy
What is the output?
#include <iostream>
using namespace std;
class IGreeter {
public:
virtual void greet(const string& name) const = 0;
virtual ~IGreeter() {}
};
class FormalGreeter : public IGreeter {
public:
void greet(const string& name) const override {
cout << "Good morning, " << name << endl;
}
};
class CasualGreeter : public IGreeter {
public:
void greet(const string& name) const override {
cout << "Hey, " << name << "!" << endl;
}
};
int main() {
IGreeter* g1 = new FormalGreeter();
IGreeter* g2 = new CasualGreeter();
g1->greet("Arjun");
g2->greet("Kavya");
delete g1; delete g2;
return 0;
}Two concrete classes implementing the same interface, called through interface pointers.
Good morning, ArjunHey, Kavya!Question 6
Medium
What is the output?
#include <iostream>
using namespace std;
class Base {
public:
virtual void show() = 0;
virtual ~Base() {}
};
void Base::show() {
cout << "Base default" << endl;
}
class Derived : public Base {
public:
void show() override {
Base::show();
cout << "Derived extra" << endl;
}
};
int main() {
Derived d;
d.show();
return 0;
}A pure virtual function can have a definition. Derived calls it with Base::show().
Base defaultDerived extraQuestion 7
Medium
What is the output?
#include <iostream>
using namespace std;
class AbstractBase {
public:
virtual ~AbstractBase() = 0;
void work() { cout << "Working" << endl; }
};
AbstractBase::~AbstractBase() { cout << "~AbstractBase" << endl; }
class Concrete : public AbstractBase {
public:
~Concrete() override { cout << "~Concrete" << endl; }
};
int main() {
AbstractBase* p = new Concrete();
p->work();
delete p;
return 0;
}Pure virtual destructor makes the class abstract. It still needs a definition.
Working~Concrete~AbstractBaseQuestion 8
Medium
What is the output?
#include <iostream>
using namespace std;
class IPrint {
public:
virtual void print() const = 0;
virtual ~IPrint() {}
};
class ISave {
public:
virtual void save() const = 0;
virtual ~ISave() {}
};
class Doc : public IPrint, public ISave {
string content;
public:
Doc(string c) : content(c) {}
void print() const override { cout << "Print: " << content << endl; }
void save() const override { cout << "Save: " << content << endl; }
};
int main() {
Doc d("Hello World");
IPrint* p = &d;
ISave* s = &d;
p->print();
s->save();
return 0;
}Doc implements two interfaces. Each interface pointer can access only its own methods.
Print: Hello WorldSave: Hello WorldQuestion 9
Medium
What is the output?
#include <iostream>
using namespace std;
class Animal {
public:
virtual void sound() const = 0;
virtual void move() const = 0;
virtual ~Animal() {}
};
class Pet : public Animal {
public:
void move() const override { cout << "Walks at home" << endl; }
};
class Dog : public Pet {
public:
void sound() const override { cout << "Bark" << endl; }
};
int main() {
Dog d;
d.sound();
d.move();
return 0;
}Pet implements move() but not sound(). Dog implements sound(). Together, all pure virtuals are covered.
BarkWalks at homeQuestion 10
Hard
What is the output?
#include <iostream>
using namespace std;
class A {
public:
virtual void f() = 0;
virtual ~A() {}
};
void A::f() { cout << "A::f" << endl; }
class B : public A {
public:
void f() override { cout << "B::f" << endl; }
};
class C : public A {
public:
void f() override {
A::f();
cout << "C::f" << endl;
}
};
int main() {
A* arr[] = { new B(), new C() };
for (int i = 0; i < 2; i++) {
arr[i]->f();
cout << "---" << endl;
delete arr[i];
}
return 0;
}B ignores A::f(). C calls A::f() explicitly before adding its own output.
B::f---A::fC::f---Question 11
Hard
Does this code compile? If so, what is the output?
#include <iostream>
using namespace std;
class Shape {
public:
virtual double area() const = 0;
virtual ~Shape() {}
};
class Circle : public Shape {
double r;
public:
Circle(double r) : r(r) {}
double area() const override { return 3.14 * r * r; }
};
void printArea(Shape s) {
cout << s.area() << endl;
}
int main() {
Circle c(5);
printArea(c);
return 0;
}printArea takes Shape by value. Can you copy an abstract type?
Compilation error: cannot declare parameter 's' to be of abstract type 'Shape'.
Question 12
Hard
What is the output?
#include <iostream>
using namespace std;
class IEngine {
public:
virtual void start() = 0;
virtual ~IEngine() {}
};
class IElectric {
public:
virtual int battery() const = 0;
virtual ~IElectric() {}
};
class HybridCar : public IEngine, public IElectric {
public:
void start() override { cout << "Hybrid started" << endl; }
int battery() const override { return 85; }
};
int main() {
HybridCar h;
IEngine* e = &h;
IElectric* el = &h;
e->start();
cout << "Battery: " << el->battery() << "%" << endl;
return 0;
}HybridCar implements two interfaces. Each pointer accesses only its interface's methods.
Hybrid startedBattery: 85%Question 13
Hard
What is the output?
#include <iostream>
using namespace std;
class Base {
public:
virtual void f() { cout << "Base::f" << endl; }
virtual void g() = 0;
virtual ~Base() {}
};
class Mid : public Base {
public:
void g() override { cout << "Mid::g" << endl; }
};
class Leaf : public Mid {
public:
void f() override { cout << "Leaf::f" << endl; }
};
int main() {
Base* b = new Leaf();
b->f();
b->g();
delete b;
return 0;
}f() is virtual (not pure) in Base, overridden in Leaf. g() is pure virtual in Base, implemented in Mid, inherited by Leaf.
Leaf::fMid::gQuestion 14
Hard
What is the output?
#include <iostream>
using namespace std;
class Shape {
public:
virtual void draw() const = 0;
virtual ~Shape() { cout << "~Shape" << endl; }
};
class Circle : public Shape {
public:
void draw() const override { cout << "Circle" << endl; }
~Circle() { cout << "~Circle" << endl; }
};
class ColoredCircle : public Circle {
string color;
public:
ColoredCircle(string c) : color(c) {}
void draw() const override { cout << color << " Circle" << endl; }
~ColoredCircle() { cout << "~ColoredCircle" << endl; }
};
int main() {
Shape* s = new ColoredCircle("Red");
s->draw();
delete s;
return 0;
}Three-level hierarchy. Virtual destructor. All three destructors should run.
Red Circle~ColoredCircle~Circle~ShapeMixed & Application Questions
Question 1
Easy
What makes a class abstract in C++?
Think about pure virtual functions.
A class is abstract if it has at least one pure virtual function (declared with = 0). An abstract class cannot be instantiated directly. Only concrete derived classes that implement all pure virtual functions can be instantiated.
Question 2
Easy
How do you create an interface in C++?
C++ does not have an interface keyword.
In C++, an interface is created by writing a class with only pure virtual functions and a virtual destructor, with no data members. By convention, interface names are often prefixed with 'I' (e.g., IDrawable, ISerializable).
Question 3
Easy
What is the output?
#include <iostream>
using namespace std;
class Calculator {
public:
virtual int compute(int a, int b) const = 0;
virtual ~Calculator() {}
};
class Adder : public Calculator {
public:
int compute(int a, int b) const override { return a + b; }
};
class Multiplier : public Calculator {
public:
int compute(int a, int b) const override { return a * b; }
};
int main() {
Calculator* c1 = new Adder();
Calculator* c2 = new Multiplier();
cout << c1->compute(3, 4) << endl;
cout << c2->compute(3, 4) << endl;
delete c1; delete c2;
return 0;
}Two concrete classes implementing the same abstract interface.
712Question 4
Medium
What is the output?
#include <iostream>
using namespace std;
class A {
public:
virtual void f() = 0;
void g() { cout << "A::g calls f: "; f(); }
virtual ~A() {}
};
class B : public A {
public:
void f() override { cout << "B::f" << endl; }
};
int main() {
B b;
b.g();
return 0;
}g() is non-virtual in A. It calls f() which is virtual. Which f() runs?
A::g calls f: B::fQuestion 5
Medium
Can a pure virtual function have a definition in C++? If so, how is it called?
Think about providing a default implementation that derived classes can optionally use.
Yes, a pure virtual function can have a definition (body) provided outside the class. The class is still abstract and cannot be instantiated. Derived classes can call the base definition using Base::func(). This allows providing optional default behavior while still forcing derived classes to override.
Question 6
Medium
What is the output?
#include <iostream>
using namespace std;
class Shape {
public:
virtual double area() const = 0;
virtual ~Shape() {}
bool isLargerThan(const Shape& other) const {
return area() > other.area();
}
};
class Circle : public Shape {
double r;
public:
Circle(double r) : r(r) {}
double area() const override { return 3.14 * r * r; }
};
class Square : public Shape {
double s;
public:
Square(double s) : s(s) {}
double area() const override { return s * s; }
};
int main() {
Circle c(5);
Square sq(8);
cout << c.isLargerThan(sq) << endl;
cout << sq.isLargerThan(c) << endl;
return 0;
}isLargerThan is non-virtual and calls the virtual area() on both this and other.
10Question 7
Medium
What is the abstract destructor pattern and when would you use it?
Think about a class where all methods have implementations but you still want it to be abstract.
The abstract destructor pattern declares the destructor as pure virtual (virtual ~Base() = 0) while providing a definition outside the class. This makes the class abstract even when all other methods have implementations. You use it when you want to prevent direct instantiation of a base class that has no pure virtual behavior methods.
Question 8
Hard
What is the output?
#include <iostream>
using namespace std;
class ILog {
public:
virtual void log(const string& msg) const = 0;
virtual ~ILog() {}
};
class INotify {
public:
virtual void notify(const string& msg) const = 0;
virtual ~INotify() {}
};
class Service : public ILog, public INotify {
public:
void log(const string& msg) const override {
cout << "[LOG] " << msg << endl;
}
void notify(const string& msg) const override {
cout << "[NOTIFY] " << msg << endl;
}
};
void doLog(const ILog& logger) { logger.log("System started"); }
void doNotify(const INotify& notifier) { notifier.notify("Alert!"); }
int main() {
Service s;
doLog(s);
doNotify(s);
return 0;
}Service implements two interfaces. Each function accepts a different interface reference.
[LOG] System started[NOTIFY] Alert!Question 9
Hard
What is the output?
#include <iostream>
using namespace std;
class Base {
public:
virtual void action() = 0;
virtual ~Base() = 0;
};
Base::~Base() { cout << "~Base" << endl; }
void Base::action() { cout << "Base::action" << endl; }
class Mid : public Base {
public:
void action() override {
Base::action();
cout << "Mid::action" << endl;
}
~Mid() override { cout << "~Mid" << endl; }
};
class Leaf : public Mid {
public:
void action() override {
Mid::action();
cout << "Leaf::action" << endl;
}
~Leaf() override { cout << "~Leaf" << endl; }
};
int main() {
Base* p = new Leaf();
p->action();
delete p;
return 0;
}Each level calls the parent's action() before adding its own. The destructor chain runs in reverse.
Base::actionMid::actionLeaf::action~Leaf~Mid~BaseQuestion 10
Hard
Does this code compile?
#include <iostream>
using namespace std;
class IComparable {
public:
virtual bool lessThan(const IComparable& other) const = 0;
virtual ~IComparable() {}
};
class Score : public IComparable {
int val;
public:
Score(int v) : val(v) {}
bool lessThan(const IComparable& other) const override {
const Score& s = dynamic_cast<const Score&>(other);
return val < s.val;
}
};
int main() {
Score a(85), b(92);
cout << a.lessThan(b) << endl;
cout << b.lessThan(a) << endl;
return 0;
}dynamic_cast on a reference throws bad_cast on failure. Here both are Score objects.
10Question 11
Hard
Why is multiple inheritance of interfaces safer than multiple inheritance of concrete classes?
Think about data members and the diamond problem.
Interfaces (classes with only pure virtual functions) have no data members and no implementation. Multiple inheritance of interfaces cannot cause data duplication, ambiguous member access, or the diamond problem's data ambiguity. With concrete classes, multiple inheritance can lead to duplicate base class subobjects, ambiguous function calls, and the need for virtual inheritance.
Multiple Choice Questions
MCQ 1
What makes a class abstract in C++?
Answer: B
B is correct. C++ does not have an
B is correct. C++ does not have an
abstract keyword. A class is abstract if it has at least one pure virtual function (declared with = 0).MCQ 2
How is a pure virtual function declared?
Answer: A
A is correct. A pure virtual function is declared with
A is correct. A pure virtual function is declared with
= 0 at the end. = delete is a different feature that explicitly deletes a function.MCQ 3
Can you create an object of an abstract class?
Answer: B
B is correct. Abstract classes cannot be instantiated. You can have pointers and references to an abstract class type, but the actual object must be a concrete derived class.
B is correct. Abstract classes cannot be instantiated. You can have pointers and references to an abstract class type, but the actual object must be a concrete derived class.
MCQ 4
What is an interface in C++?
Answer: B
B is correct. C++ has no
B is correct. C++ has no
interface keyword. By convention, an interface is a class with only pure virtual functions (and typically a virtual destructor), with no data members or implementations.MCQ 5
What happens if a derived class does not implement all pure virtual functions?
Answer: C
C is correct. If a derived class does not implement all pure virtual functions from its base, it inherits the remaining pure virtual functions and is itself abstract. It cannot be instantiated.
C is correct. If a derived class does not implement all pure virtual functions from its base, it inherits the remaining pure virtual functions and is itself abstract. It cannot be instantiated.
MCQ 6
Can a pure virtual function have a definition (body)?
Answer: B
B is correct. A pure virtual function can have a definition provided outside the class body. The class is still abstract. Derived classes can call it with
B is correct. A pure virtual function can have a definition provided outside the class body. The class is still abstract. Derived classes can call it with
Base::func() to use the default behavior.MCQ 7
What is required when using a pure virtual destructor?
Answer: B
B is correct. A pure virtual destructor must have a definition provided outside the class because destructors are always called in the inheritance chain. Without the definition, you get a linker error.
B is correct. A pure virtual destructor must have a definition provided outside the class because destructors are always called in the inheritance chain. Without the definition, you get a linker error.
MCQ 8
Why is multiple inheritance of interfaces generally safe?
Answer: B
B is correct. The diamond problem's ambiguity comes from duplicate data members. Interfaces have no data members and no implementation, so inheriting from multiple interfaces cannot cause data duplication or ambiguous member access.
B is correct. The diamond problem's ambiguity comes from duplicate data members. Interfaces have no data members and no implementation, so inheriting from multiple interfaces cannot cause data duplication or ambiguous member access.
MCQ 9
Which of the following can an abstract class have?
Answer: B
B is correct. An abstract class can have pure virtual functions, regular virtual functions, non-virtual functions, data members, constructors, and destructors. It just needs at least one pure virtual function to be abstract.
B is correct. An abstract class can have pure virtual functions, regular virtual functions, non-virtual functions, data members, constructors, and destructors. It just needs at least one pure virtual function to be abstract.
MCQ 10
Can you have a pointer or reference to an abstract class?
Answer: C
C is correct. You can have
C is correct. You can have
Shape* s or Shape& s where Shape is abstract. The actual object must be concrete. This is the foundation of runtime polymorphism.MCQ 11
What is the output?
class A { public: virtual void f() = 0; virtual ~A(){} };
void A::f() { cout << "A"; }
class B : public A { public: void f() override { A::f(); cout << "B"; } };
int main() { B b; b.f(); }Answer: B
B is correct.
B is correct.
B::f() calls A::f() which prints "A", then prints "B". The result is "AB". A pure virtual function with a definition can be called explicitly.MCQ 12
Which statement about abstract classes is FALSE?
Answer: C
C is correct (it is the false statement). You cannot create arrays of abstract class objects because that would require instantiating the abstract class. You CAN have arrays of pointers (
C is correct (it is the false statement). You cannot create arrays of abstract class objects because that would require instantiating the abstract class. You CAN have arrays of pointers (
Shape* arr[10]) or references to abstract types.MCQ 13
When should you use an abstract class instead of an interface?
Answer: B
B is correct. Use an abstract class when derived classes share common data or implementation. Use an interface when you only want to define a contract with no shared state or implementation.
B is correct. Use an abstract class when derived classes share common data or implementation. Use an interface when you only want to define a contract with no shared state or implementation.
Coding Challenges
Challenge 1: Shape Hierarchy with Abstract Base
EasyCreate an abstract Shape class with pure virtual area() and perimeter(). Implement Circle, Rectangle, and Triangle. Store pointers in a Shape* array. Print each shape's name, area, and perimeter.
Sample Input
Circle r=5, Rectangle 4x6, Triangle 3-4-5
Sample Output
Circle: area=78.54, perimeter=31.42
Rectangle: area=24.00, perimeter=20.00
Triangle: area=6.00, perimeter=12.00
Use pure virtual functions. Use override. Include virtual destructor.
#include <iostream>
#include <cmath>
using namespace std;
class Shape {
public:
virtual double area() const = 0;
virtual double perimeter() const = 0;
virtual string name() const = 0;
virtual ~Shape() {}
};
class Circle : public Shape {
double r;
public:
Circle(double r) : r(r) {}
double area() const override { return M_PI * r * r; }
double perimeter() const override { return 2 * M_PI * r; }
string name() const override { return "Circle"; }
};
class Rectangle : public Shape {
double w, h;
public:
Rectangle(double w, double h) : w(w), h(h) {}
double area() const override { return w * h; }
double perimeter() const override { return 2 * (w + h); }
string name() const override { return "Rectangle"; }
};
class Triangle : public Shape {
double a, b, c;
public:
Triangle(double a, double b, double c) : a(a), b(b), c(c) {}
double area() const override {
double s = (a + b + c) / 2;
return sqrt(s * (s-a) * (s-b) * (s-c));
}
double perimeter() const override { return a + b + c; }
string name() const override { return "Triangle"; }
};
int main() {
Shape* shapes[] = { new Circle(5), new Rectangle(4, 6), new Triangle(3, 4, 5) };
for (int i = 0; i < 3; i++) {
printf("%s: area=%.2f, perimeter=%.2f\n",
shapes[i]->name().c_str(), shapes[i]->area(), shapes[i]->perimeter());
delete shapes[i];
}
return 0;
}Challenge 2: Multiple Interface Implementation
MediumCreate interfaces IReadable (with read()), IWritable (with write(string)), and IClosable (with close()). Create a File class that implements all three. Create a process() function that takes an IReadable& and reads, and a save() function that takes an IWritable& and writes.
Sample Input
File operations
Sample Output
Reading from data.txt
Writing 'Hello World' to data.txt
Closing data.txt
Each interface should have only pure virtual functions and virtual destructor. Use references.
#include <iostream>
#include <string>
using namespace std;
class IReadable {
public:
virtual string read() const = 0;
virtual ~IReadable() {}
};
class IWritable {
public:
virtual void write(const string& data) = 0;
virtual ~IWritable() {}
};
class IClosable {
public:
virtual void close() = 0;
virtual ~IClosable() {}
};
class File : public IReadable, public IWritable, public IClosable {
string filename;
public:
File(string name) : filename(name) {}
string read() const override {
cout << "Reading from " << filename << endl;
return "file contents";
}
void write(const string& data) override {
cout << "Writing '" << data << "' to " << filename << endl;
}
void close() override {
cout << "Closing " << filename << endl;
}
};
void process(const IReadable& r) { r.read(); }
void save(IWritable& w, const string& data) { w.write(data); }
int main() {
File f("data.txt");
process(f);
save(f, "Hello World");
f.close();
return 0;
}Challenge 3: Database Abstraction Layer
HardCreate an abstract Database class with pure virtual connect(), query(string), and disconnect(). Add a non-virtual executeWithLog(string) that logs and calls query(). Implement MySQL and PostgreSQL classes. Process an array of Database* pointers.
Sample Input
Two databases, each executing a query
Sample Output
[LOG] SELECT * FROM users
MySQL: Executing 'SELECT * FROM users'
[LOG] SELECT * FROM users
PostgreSQL: Executing 'SELECT * FROM users'
Use abstract class with mixed pure virtual and non-virtual. Demonstrate that non-virtual methods call virtual methods polymorphically.
#include <iostream>
#include <string>
using namespace std;
class Database {
public:
virtual void connect() = 0;
virtual string query(const string& sql) = 0;
virtual void disconnect() = 0;
virtual ~Database() {}
void executeWithLog(const string& sql) {
cout << "[LOG] " << sql << endl;
query(sql);
}
};
class MySQL : public Database {
public:
void connect() override { cout << "MySQL connected" << endl; }
string query(const string& sql) override {
cout << "MySQL: Executing '" << sql << "'" << endl;
return "mysql result";
}
void disconnect() override { cout << "MySQL disconnected" << endl; }
};
class PostgreSQL : public Database {
public:
void connect() override { cout << "PostgreSQL connected" << endl; }
string query(const string& sql) override {
cout << "PostgreSQL: Executing '" << sql << "'" << endl;
return "pg result";
}
void disconnect() override { cout << "PostgreSQL disconnected" << endl; }
};
int main() {
Database* dbs[] = { new MySQL(), new PostgreSQL() };
for (int i = 0; i < 2; i++) {
dbs[i]->connect();
dbs[i]->executeWithLog("SELECT * FROM users");
dbs[i]->disconnect();
cout << "---" << endl;
delete dbs[i];
}
return 0;
}Challenge 4: Plugin System with Interface
HardCreate an IPlugin interface with name(), version(), initialize(), execute(string), and shutdown(). Create LogPlugin and CachePlugin implementations. Create a PluginManager that stores IPlugin* pointers and has loadAll(), runAll(string command), and unloadAll() methods.
Sample Input
Run all plugins with command 'process-data'
Sample Output
Loading LogPlugin v1.0...
Loading CachePlugin v2.1...
LogPlugin: Logging 'process-data'
CachePlugin: Caching 'process-data'
Unloading CachePlugin...
Unloading LogPlugin...
Interface must have only pure virtual functions. Manager must work with IPlugin* only.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class IPlugin {
public:
virtual string name() const = 0;
virtual string version() const = 0;
virtual void initialize() = 0;
virtual void execute(const string& cmd) = 0;
virtual void shutdown() = 0;
virtual ~IPlugin() {}
};
class LogPlugin : public IPlugin {
public:
string name() const override { return "LogPlugin"; }
string version() const override { return "1.0"; }
void initialize() override { cout << "Loading " << name() << " v" << version() << "..." << endl; }
void execute(const string& cmd) override { cout << name() << ": Logging '" << cmd << "'" << endl; }
void shutdown() override { cout << "Unloading " << name() << "..." << endl; }
};
class CachePlugin : public IPlugin {
public:
string name() const override { return "CachePlugin"; }
string version() const override { return "2.1"; }
void initialize() override { cout << "Loading " << name() << " v" << version() << "..." << endl; }
void execute(const string& cmd) override { cout << name() << ": Caching '" << cmd << "'" << endl; }
void shutdown() override { cout << "Unloading " << name() << "..." << endl; }
};
class PluginManager {
vector<IPlugin*> plugins;
public:
void addPlugin(IPlugin* p) { plugins.push_back(p); }
void loadAll() { for (auto* p : plugins) p->initialize(); }
void runAll(const string& cmd) { for (auto* p : plugins) p->execute(cmd); }
void unloadAll() {
for (int i = plugins.size()-1; i >= 0; i--) plugins[i]->shutdown();
}
~PluginManager() { for (auto* p : plugins) delete p; }
};
int main() {
PluginManager mgr;
mgr.addPlugin(new LogPlugin());
mgr.addPlugin(new CachePlugin());
mgr.loadAll();
mgr.runAll("process-data");
mgr.unloadAll();
return 0;
}Need to Review the Concepts?
Go back to the detailed notes for this chapter.
Read Chapter NotesWant to learn C++ with a live mentor?
Explore our C++ Masterclass