后期绑定有哪些优点?在C++中的函数指针的上下文中给出一个示例

Viv*_*yan -1 c c++ function-pointers late-binding

首先,让我澄清这个问题并不能清楚地解释我的怀疑.设置上下文清晰.我在C/C++中专门针对函数指针问这个问题.

我知道早期绑定和后期绑定之间的区别以及它是如何工作的.我想要了解的是以下一个使用C/C++中的函数指针的示例:

在许多教科书中,已经提到:

后期绑定的优点是它比早期绑定更灵活,因为关于调用哪个函数的决定不需要在运行时进行.

另外,它提到:

使用后期绑定,程序必须读取指针中保存的地址,然后跳转到该地址.这涉及一个额外的步骤,使其稍慢.

#include <iostream>
using namespace std;

int Add(int nX, int nY)
{
    return nX + nY;
}

int Subtract(int nX, int nY)
{
    return nX - nY;
}

int Multiply(int nX, int nY)
{
    return nX * nY;
}

int main()
{
    int nX;
    cout << "Enter a number: ";
    cin >> nX;

    int nY;
    cout << "Enter another number: ";
    cin >> nY;

    int nOperation;
    do
    {
        cout << "Enter an operation (0=add, 1=subtract, 2=multiply): ";
        cin >> nOperation;
    } while (nOperation < 0 || nOperation > 2);

    // Create a function pointer named pFcn (yes, the syntax is ugly)
    int (*pFcn)(int, int);

    // Set pFcn to point to the function the user chose
    switch (nOperation)
    {
        case 0: pFcn = Add; break;
        case 1: pFcn = Subtract; break;
        case 2: pFcn = Multiply; break;
    }

    // Call the function that pFcn is pointing to with nX and nY as parameters
    cout << "The answer is: " << pFcn(nX, nY) << endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这里,没有使用后期绑定和早期绑定的优点,因为下面的例子应该是首选.

int nResult = 0;
switch (nOperation)
{
    case 0: nResult = Add(nX, nY); break;
    case 1: nResult = Subtract(nX, nY); break;
    case 2: nResult = Multiply(nX, nY); break;
}

cout << "The answer is: " << nResult << endl;
Run Code Online (Sandbox Code Playgroud)

有人可以用一个简单的例子来解释一下,后期绑定是有利的,为什么有人会选择它而不是早期绑定?

Nic*_*las 5

好的,我将跳过整个"早期绑定与后期绑定"定义问题并假装你问"为什么有人会使用函数指针而不是switch语句?"

因为函数指针更灵活.它们不是静态的.让我们来看看代码的业务结束:

int InvokeOperation(int nOperation, int nX, int nY)
{
    switch (nOperation)
    {
        case 0: return Add(nX, nY);
        case 1: return Subtract(nX, nY);
        case 2: return Multiply(nX, nY);
    }
}
Run Code Online (Sandbox Code Playgroud)

这很好,功能齐全.但它并不灵活.为什么?因为可以调用的所有函数都是由InvokeOperation; 如果要添加新操作,则必须能够更改InvokeOperation.

相比之下,如果使用函数指针,则可以构建整个操作注册表:

using Func = int(*)(int, int);
struct Op{Func func; std::string name;};
std::vector<Func> funcs =
{
    {&Add, "Add"},
    {&Subtract, "Subtract"},
    {&Multiply, "Multiply"},
};

int InvokeOperation(int nOperation, int nX, int nY)
{
    return funcs[nOperation].func(nX, nY);
}
Run Code Online (Sandbox Code Playgroud)

现在,如果要添加更多操作,只需插入元素即可funcs.如果InvokeOperation是某些图书馆的一部分,您不一定有权更改它.使用静态绑定,您将拥有一个不灵活的系统; 它所支持的是它将永远支持的东西.

使用动态绑定,您可以添加所需的任何内容,无论您是否有权直接修改库.