Pointers to Members

Serializing Member Function Pointers

What's the best way to serialize/deserialize member function pointers for saving game state or network communication?

Abstract art representing computer programming

Serializing member function pointers directly is not recommended because they contain implementation-specific memory addresses. Instead, we should serialize an identifier that can be mapped back to the appropriate function.

Enum-Based Approach

Here's how to implement this safely using an enum:

#include <iostream>
#include <map>

class Character {
public:
  enum class AbilityType {
    Fireball,
    IceBlast,
    Lightning
  };

  using AbilityFunc = void (Character::*)();

  void Fireball() {
    std::cout << "Cast Fireball!\n";
  }

  void IceBlast() {
    std::cout << "Cast Ice Blast!\n";
  }

  void Lightning() {
    std::cout << "Cast Lightning!\n";
  }

  // Map ability types to member functions
  static std::map<AbilityType, AbilityFunc>
  AbilityMap;

  // Serialize ability to enum
  AbilityType
    SerializeAbility(AbilityFunc Func) {
    for (const auto& [type, ptr] : AbilityMap) {
      if (ptr == Func) return type;
    }
    throw std::runtime_error("Unknown ability");
  }

  // Deserialize enum to ability
  AbilityFunc
    DeserializeAbility(AbilityType Type) {
    return AbilityMap[Type];
  }
};

// Initialize static map
std::map<Character::AbilityType,
         Character::AbilityFunc>
Character::AbilityMap =
{
  {AbilityType::Fireball, &Character::Fireball},
  {AbilityType::IceBlast, &Character::IceBlast},
  {
    AbilityType::Lightning,
    &Character::Lightning}};

int main() {
  Character player;

  // Store current ability
  auto currentAbility = &Character::Fireball;

  // Serialize
  auto serialized = player.SerializeAbility(
    currentAbility);

  // Save to file/network (example just prints)
  std::cout << "Saved ability ID: " <<
    static_cast<int>(serialized) << '\n';

  // Load and deserialize
  auto loadedAbility = player.
    DeserializeAbility(serialized);

  // Use restored ability
  (player.*loadedAbility)();
}
Saved ability ID: 0
Cast Fireball!

String-Based Approach

In this variation, we use a std::string:

#include <iostream>
#include <map>
#include <string>

class Character {
public:
  using AbilityFunc = void (Character::*)();

  void Fireball() {
    std::cout << "Cast Fireball!\n";
  }

  void IceBlast() {
    std::cout << "Cast Ice Blast!\n";
  }

private:
  static std::map<std::string, AbilityFunc>
  AbilityMap;

public:
  std::string
    SerializeAbility(AbilityFunc Func) {
    for (const auto& [name, ptr] : AbilityMap) {
      if (ptr == Func) return name;
    }
    return "unknown";
  }

  AbilityFunc DeserializeAbility(
    const std::string& Name) {
    auto it = AbilityMap.find(Name);
    if (it != AbilityMap.end()) {
      return it->second;
    }
    throw std::runtime_error(
      "Unknown ability: " + Name);
  }
};

// Initialize static map
std::map<std::string, Character::AbilityFunc>
Character::AbilityMap = {
  {"fireball", &Character::Fireball},
  {"ice_blast", &Character::IceBlast}};

int main() {
  Character player;

  // Serialize
  auto serialized = player.SerializeAbility(
    &Character::Fireball);
  std::cout << "Saved ability name: " <<
    serialized << '\n';

  // Deserialize and use
  auto loadedAbility = player.
    DeserializeAbility(serialized);
  (player.*loadedAbility)();
}
Saved ability name: fireball
Cast Fireball!

Key considerations:

  • Never serialize raw function pointers
  • Use stable identifiers (enums, strings, integers)
  • Maintain a mapping between identifiers and functions
  • Consider versioning for save game compatibility
  • Handle missing/invalid functions gracefully
  • Consider using a factory pattern for complex scenarios

This approach ensures safe serialization while maintaining the flexibility of member function pointers.

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

A computer programmer
Part of the course:

Professional C++

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

Free, unlimited access

This course includes:

  • 125 Lessons
  • 550+ Code Samples
  • 96% 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