C++ Function Pointer | 'Function Pointer' Guide

C++ Function Pointer | 'Function Pointer' Guide

이 글의 핵심

int add(int a, int b) { return a + b; }.

What is Function Pointer?

Pointer that stores address of function

Below is an implementation example using C++. Understand the role of each part while examining the code.

int add(int a, int b) {
    return a + b;
}

int main() {
    // Declare function pointer
    int (*funcPtr)(int, int) = add;
    
    // Call
    int result = funcPtr(3, 4);  // 7
    std::cout << result << std::endl;
}

Basic Syntax

Below is an implementation example using C++. Understand the role of each part while examining the code.

// Declare function pointer
int (*ptr)(int, int);

// Assign function
int add(int a, int b) { return a + b; }
ptr = add;
// Or
ptr = &add;

// Call
int result = ptr(3, 4);
// Or
int result = (*ptr)(3, 4);

Simplify with typedef/using

Here is detailed implementation code using C++. Import necessary modules. Understand the role of each part while examining the code.

// typedef
typedef int (*Operation)(int, int);

// using (recommended)
using Operation = int(*)(int, int);

int add(int a, int b) { return a + b; }
int multiply(int a, int b) { return a * b; }

int main() {
    Operation op = add;
    std::cout << op(3, 4) << std::endl;  // 7
    
    op = multiply;
    std::cout << op(3, 4) << std::endl;  // 12
}

Practical Examples

Example 1: Callback Function

Here is detailed implementation code using C++. Import necessary modules, process data with loops. Understand the role of each part while examining the code.

#include <vector>

void forEach(const std::vector<int>& vec, void (*callback)(int)) {
    for (int x : vec) {
        callback(x);
    }
}

void printValue(int x) {
    std::cout << x << " ";
}

void printSquare(int x) {
    std::cout << x * x << " ";
}

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    
    forEach(numbers, printValue);   // 1 2 3 4 5
    std::cout << std::endl;
    
    forEach(numbers, printSquare);  // 1 4 9 16 25
    std::cout << std::endl;
}

Example 2: Calculator

Here is detailed implementation code using C++. Import necessary modules. Understand the role of each part while examining the code.

using Operation = int(*)(int, int);

int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int multiply(int a, int b) { return a * b; }
int divide(int a, int b) { return b != 0 ? a / b : 0; }

int calculate(int a, int b, Operation op) {
    return op(a, b);
}

int main() {
    std::cout << calculate(10, 5, add) << std::endl;       // 15
    std::cout << calculate(10, 5, subtract) << std::endl;  // 5
    std::cout << calculate(10, 5, multiply) << std::endl;  // 50
    std::cout << calculate(10, 5, divide) << std::endl;    // 2
}

Example 3: Function Table

Here is detailed implementation code using C++. Import necessary modules, process data with loops, perform branching with conditionals. Understand the role of each part while examining the code.

#include <map>
#include <string>

using Command = void(*)();

void cmdHelp() {
    std::cout << "Help" << std::endl;
}

void cmdQuit() {
    std::cout << "Quit" << std::endl;
}

void cmdStatus() {
    std::cout << "Status check" << std::endl;
}

int main() {
    std::map<std::string, Command> commands = {
        {"help", cmdHelp},
        {"quit", cmdQuit},
        {"status", cmdStatus}
    };
    
    std::string input;
    while (true) {
        std::cout << "> ";
        std::cin >> input;
        
        if (input == "quit") break;
        
        auto it = commands.find(input);
        if (it != commands.end()) {
            it->second();  // Call function
        } else {
            std::cout << "Unknown command" << std::endl;
        }
    }
}

Example 4: Sort Comparison Function

Here is detailed implementation code using C++. Import necessary modules, process data with loops. Understand the role of each part while examining the code.

#include <algorithm>
#include <vector>

bool ascending(int a, int b) {
    return a < b;
}

bool descending(int a, int b) {
    return a > b;
}

bool byAbsoluteValue(int a, int b) {
    return std::abs(a) < std::abs(b);
}

void sortVector(std::vector<int>& vec, bool (*compare)(int, int)) {
    std::sort(vec.begin(), vec.end(), compare);
}

int main() {
    std::vector<int> numbers = {-5, 2, -8, 1, 9, -3};
    
    sortVector(numbers, ascending);
    for (int x : numbers) std::cout << x << " ";
    std::cout << std::endl;  // -8 -5 -3 1 2 9
    
    sortVector(numbers, descending);
    for (int x : numbers) std::cout << x << " ";
    std::cout << std::endl;  // 9 2 1 -3 -5 -8
    
    sortVector(numbers, byAbsoluteValue);
    for (int x : numbers) std::cout << x << " ";
    std::cout << std::endl;  // 1 2 -3 -5 -8 9
}

std::function (C++11)

Here is detailed implementation code using C++. Import necessary modules. Understand the role of each part while examining the code.

#include <functional>

int add(int a, int b) {
    return a + b;
}

int main() {
    // Function pointer
    int (*ptr)(int, int) = add;
    
    // std::function (more flexible)
    std::function<int(int, int)> func = add;
    
    // Can also store lambda
    func = [](int a, int b) { return a * b; };
    
    std::cout << func(3, 4) << std::endl;  // 12
}

Member Function Pointer

Here is detailed implementation code using C++. Define a class to encapsulate data and functionality. Understand the role of each part while examining the code.

class Calculator {
public:
    int add(int a, int b) {
        return a + b;
    }
    
    int multiply(int a, int b) {
        return a * b;
    }
};

int main() {
    Calculator calc;
    
    // Member function pointer
    int (Calculator::*funcPtr)(int, int) = &Calculator::add;
    
    // Call
    int result = (calc.*funcPtr)(3, 4);  // 7
    std::cout << result << std::endl;
    
    // Call with pointer
    Calculator* ptr = &calc;
    result = (ptr->*funcPtr)(3, 4);
    std::cout << result << std::endl;
}

Common Issues

Issue 1: Syntax Complexity

Below is an implementation example using C++. Import necessary modules. Try running the code directly to check its operation.

// ❌ Complex syntax
int (*funcPtr)(int, int);

// ✅ Simplify with using
using Operation = int(*)(int, int);
Operation funcPtr;

Issue 2: nullptr Check

Below is an implementation example using C++. Import necessary modules, perform branching with conditionals. Understand the role of each part while examining the code.

using Callback = void(*)();

void execute(Callback cb) {
    // ❌ No nullptr check
    // cb();  // Can crash
    
    // ✅ nullptr check
    if (cb) {
        cb();
    }
}

Issue 3: Lambda Capture

Below is an implementation example using C++. Try running the code directly to check its operation.

int x = 10;

// ❌ Lambda with capture cannot be function pointer
// void (*ptr)() = [x]() { std::cout << x; };  // Error

// ✅ Use std::function
std::function<void()> func = [x]() { std::cout << x; };

Issue 4: Member Function Pointer

Below is an implementation example using C++. Define a class to encapsulate data and functionality. Understand the role of each part while examining the code.

class MyClass {
public:
    void func() {}
};

// ❌ Cannot use regular function pointer
// void (*ptr)() = &MyClass::func;  // Error

// ✅ Member function pointer
void (MyClass::*ptr)() = &MyClass::func;

MyClass obj;
(obj.*ptr)();

Function Pointer Array

Here is detailed implementation code using C++. Import necessary modules, process data with loops. Understand the role of each part while examining the code.

using Operation = int(*)(int, int);

int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int multiply(int a, int b) { return a * b; }
int divide(int a, int b) { return b != 0 ? a / b : 0; }

int main() {
    Operation operations[] = {add, subtract, multiply, divide};
    
    for (int i = 0; i < 4; i++) {
        std::cout << operations[i](10, 5) << " ";
    }
    std::cout << std::endl;  // 15 5 50 2
}

std::function vs Function Pointer

Here is detailed implementation code using C++. Import necessary modules. Understand the role of each part while examining the code.

#include <functional>

int add(int a, int b) { return a + b; }

int main() {
    // Function pointer: Functions only
    int (*ptr)(int, int) = add;
    
    // std::function: Functions, lambdas, function objects all
    std::function<int(int, int)> func1 = add;
    std::function<int(int, int)> func2 = [](int a, int b) { return a * b; };
    
    struct Multiplier {
        int operator()(int a, int b) const {
            return a * b;
        }
    };
    std::function<int(int, int)> func3 = Multiplier();
}

FAQ

Q1: When to use function pointer?

A:

  • Callback functions
  • Function tables
  • Plugin systems

Q2: std::function vs function pointer?

A:

  • Function pointer: Fast, functions only
  • std::function: Flexible, lambdas/function objects

Q3: Performance?

A: Function pointer is indirect call. Slight overhead.

Q4: Member function pointer?

A: Different syntax. &Class::func, (obj.*ptr)()

Q5: Need nullptr check?

A: Yes. Check recommended for safety.

Q6: Function pointer learning resources?

A:

  • “C++ Primer”
  • cppreference.com
  • “Effective C++“

Master function pointers for flexible callbacks! 🚀