Member Function Pointers and Binding

Member Function Pointers and Multiple Inheritance

How do we work with member function pointers in the context of multiple inheritance?

Abstract art representing computer programming

Working with member function pointers in the context of multiple inheritance can be a bit tricky, but it's definitely possible. Let's break this down step by step:

Basic Syntax

First, let's recall the basic syntax for a member function pointer:

return_type (ClassName::*pointerName)(parameter_types);

Multiple Inheritance Scenario

Now, let's consider a multiple inheritance scenario:

#include <iostream>

class Base1 {
public:
  virtual void foo() {
    std::cout << "Base1::foo\n";
  }
};

class Base2 {
public:
  virtual void bar() {
    std::cout << "Base2::bar\n";
  }
};

class Derived : public Base1, public Base2 {
public:
  void foo() override {
    std::cout << "Derived::foo\n";
  }

  void bar() override {
    std::cout << "Derived::bar\n";
  }
};

Pointer to Member Function

To create a pointer to a member function in this context, you need to specify which base class the function belongs to:

#include <iostream>

class Base1 {/*...*/};
class Base2 {/*...*/};
class Derived : Base1, Base2 {/*...*/}; int main() { void (Base1::*pBase1Foo)() = &Base1::foo; void (Base2::*pBase2Bar)() = &Base2::bar; void (Derived::*pDerivedFoo)() = &Derived::foo; void (Derived::*pDerivedBar)() = &Derived::bar; }

Using the Pointers

To use these pointers, you need an object of the appropriate type:

#include <iostream>

class Base1 {/*...*/};
class Base2 {/*...*/};
class Derived : Base1, Base2 {/*...*/}; int main() { void (Base1::*pBase1Foo)() = &Base1::foo; void (Base2::*pBase2Bar)() = &Base2::bar; void (Derived::*pDerivedFoo)() = &Derived::foo; void (Derived::*pDerivedBar)() = &Derived::bar; Derived d; Base1* pb1 = &d; Base2* pb2 = &d; (d.*pDerivedFoo)(); // Calls Derived::foo (d.*pDerivedBar)(); // Calls Derived::bar // Calls Derived::foo (virtual dispatch) (pb1->*pBase1Foo)(); // Calls Derived::bar (virtual dispatch) (pb2->*pBase2Bar)(); }
Derived::foo
Derived::bar
Derived::foo
Derived::bar

Potential Pitfalls

Be aware of potential pitfalls. Firstly, if both base classes have a function with the same name, you need to explicitly specify which one you're referring to to avoid ambiguity:

void (Derived::*pFoo)() =
  static_cast<void (Derived::*)()>(&Base1::foo);

Remember that virtual functions will still use dynamic dispatch when called through pointers to member functions.

Additionally, multiple inheritance can lead to the dreaded "diamond problem" if not handled carefully. Always use virtual inheritance when appropriate to avoid this issue.

Using std::function

For more flexibility, you can use std::function along with std::bind:

#include <functional>
#include <iostream>

class Base1 {/*...*/};
class Base2 {/*...*/};
class Derived : Base1, Base2 {/*...*/}; int main() { Derived d; std::function<void()> f = std::bind(&Base1::foo, &d); f(); }
Derived::foo

This approach can make working with member function pointers in multiple inheritance scenarios more manageable.

Remember, while multiple inheritance can be powerful, it also increases complexity. Always consider whether simpler design patterns might achieve your goals more cleanly.

Answers to questions are automatically generated and may not have been reviewed.

sdl2-promo.jpg
Part of the course:

Game Dev with SDL2

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

Free, unlimited access

This course includes:

  • 55 Lessons
  • 100+ Code Samples
  • 91% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved