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

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

Why Use Member Function Pointers?
Why do we need member function pointers when we can just call methods directly?
std::mem_fn() and Code Readability
How does using std::mem_fn() improve code readability compared to raw function pointers?
Const Member Function Pointers
How can we handle member function pointers for const member functions?
Virtual Member Function Pointers
Is it possible to create a pointer to a virtual member function? What are the implications?
Templated Member Function Pointers
How can we use member function pointers with templated member functions?
Function Pointers with Default Arguments
Can we use member function pointers with member functions that have default arguments?
Member Function Pointers and Multiple Inheritance
How do we work with member function pointers in the context of multiple inheritance?
Using Pointers to Non-Public Member Functions
Can we use member function pointers with non-public (protected or private) member functions? If so, how?
Or Ask your Own Question
Purchase the course to ask your own questions