Function Pointers with Abstract Base Classes
Can we use member function pointers with abstract base classes and derived classes?
Yes, you can use member function pointers with abstract base classes and derived classes in C++. This capability is particularly useful for implementing polymorphic behavior and designing flexible, extensible systems.
Here's how it works, along with some important considerations:
Pointing to Abstract Base Class Functions
You can create pointers to both pure virtual and non-pure virtual functions of an abstract base class:
#include <iostream>
class Shape {
public:
// Pure virtual
virtual double area() const = 0;
virtual void draw() const {
std::cout << "Drawing a shape\n";
}
};
int main() {
double (Shape::*areaPtr)() const =
&Shape::area;
void (Shape::*drawPtr)() const =
&Shape::draw;
}
Using with Derived Classes
These pointers can be used with objects of derived classes, preserving polymorphic behavior:
#include <iostream>
class Shape {/*...*/};
class Circle : public Shape {
public:
Circle(double r) : radius(r) {}
double area() const override {
return 3.14159 * radius * radius;
}
void draw() const override {
std::cout << "Drawing a circle\n";
}
private:
double radius;
};
class Rectangle : public Shape {
public:
Rectangle(double w, double h) : width(w),
height(h) {}
double area() const override {
return width * height;
}
void draw() const override {
std::cout << "Drawing a rectangle\n";
}
private:
double width, height;
};
int main() {
double (Shape::*areaPtr)() const = &
Shape::area;
void (Shape::*drawPtr)() const = &Shape::draw;
Circle c(5);
Rectangle r(3, 4);
Shape* shapes[] = {&c, &r};
for (const auto& shape : shapes) {
std::cout << "Area: " << (shape->*areaPtr)()
<< '\n';
(shape->*drawPtr)();
}
}
Area: 78.5397
Drawing a circle
Area: 12
Drawing a rectangle
std::function
and std::mem_fn()
These utilities work well with abstract base classes and derived classes:
#include <functional>
#include <iostream>
class Shape {/*...*/};
class Circle : public Shape {/*...*/};
class Rectangle : public Shape {/*...*/};
int main() {
std::function<double(const Shape&)> areaFunc =
&Shape::area;
std::function<void(const Shape&)> drawFunc = &
Shape::draw;
Circle c(5);
Rectangle r(3, 4);
std::cout << "Circle area: " << areaFunc(c)
<< "\nRectangle area: " << areaFunc(r);
drawFunc(c);
drawFunc(r);
}
Circle area: 78.5397
Rectangle area: 12
Drawing a circle
Drawing a rectangle
Storing in Data Structures
You can store these function pointers in data structures for dynamic dispatch:
#include <functional>
#include <vector>
#include <functional>
#include <iostream>
class Shape {/*...*/};
class Circle : public Shape {/*...*/};
class Rectangle : public Shape {/*...*/};
struct ShapeOperation {
std::string name;
std::function<void(const Shape&)> operation;
};
int main() {
std::vector<ShapeOperation> operations = {
{
"Calculate Area",
[](const Shape& s){
std::cout << "Area: " << s.area() <<
'\n';
}},
{"Draw", [](const Shape& s){ s.draw(); }}};
Circle c(5);
for (const auto& op : operations) {
std::cout << op.name << ": ";
op.operation(c);
}
}
Calculate Area: Area: 78.5397
Draw: Drawing a circle
Limitations and Considerations
- You cannot create an instance of an abstract base class, so you'll always be using these pointers with derived class objects.
- Be cautious when using pointers to pure virtual functions. While you can create such pointers, attempting to call a pure virtual function through a base class pointer will result in undefined behavior if the function hasn't been overridden.
- When using multiple inheritance, be aware of potential ambiguities and use explicit casting if necessary.
Using member function pointers with abstract base classes and derived classes allows for powerful, flexible designs in C++.
It enables you to work with objects polymorphically, create generic algorithms that operate on a variety of shapes (or other hierarchies), and implement plugin systems or callback mechanisms that can work with any class derived from a common abstract base.
Member Function Pointers and Binding
Explore advanced techniques for working with class member functions