Expert C++
上QQ阅读APP看书,第一时间看更新

Replacing conditionals with function pointers

Previously, we looked at memory segments, and one of the most important segments is the code segment (also called a text segment). This segment contains the program image, which is the instructions of the program that should be executed. Instructions are usually grouped into functions, which provide a unique name allowing us to call them from other functions. Functions reside in the code segment of the executable file.

A function has its address. We can declare a pointer that takes the address of the function and then use it later to call that function:

int get_answer() { return 42; }
int (*fp)() = &get_answer;
// int (*fp)() = get_answer; same as &get_answer

The function pointer can be called the same way as the original function:

get_answer(); // returns 42
fp(); // returns 42

Let's suppose we are writing a program that takes two numbers and a character from the input and executes an arithmetic operation on the numbers. The operation is specified by the character, whether it's +, -, *, or /. We implement four functions, add(), subtract(), multiply(), and divide(), and call one of them based on the value of the character input.

Instead of checking the value of the character in a bunch of if statements or a switch statement, we will map the type of the operation to the specified function using a hash table:

#include <unordered_map>
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) ? 0 : a / b; }

int main() {
std::unordered_map<char, int (*)(int, int)> operations;
operations['+'] = &add;
operations['-'] = &subtract;
operations['*'] = &multiply;
operations['/'] = &divide;
// read the input
char op;
int num1, num2;
std::cin >> num1 >> num2 >> op;
// perform the operation, as follows
operations[op](num1, num2);
}

As you can see, std::unordered_map maps char to a function pointer defined as (*)(int, int). That is, it can point to any function that takes two integers and returns an integer. 

The hash table is represented by  std::unordered_map, defined in the <unordered_map> header. We will discuss it in detail in  Chapter 6Digging into Data Structures and Algorithms in STL

Now we don't need to write the following:

if (op == '+') {
add(num1, num2);
} else if (op == '-') {
subtract(num1, num2);
} else if (op == '*') {
...

Instead, we simply call the function mapped by the character:

operations[op](num1, num2);
Though the use of a hash table is much prettier and looks more professional, you should take care of unexpected cases, such as invalid user input.