Во-первых, позвольте мне уточнить этот вопрос не объясняет мои сомнения ясно. Чтобы установить контекст ясно. Я задаю этот вопрос специально в отношении указателей на функции в 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;
}
здесь нет преимуществ использования позднего связывания и раннего связывания, как в приведенном ниже примере.
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;
Может ли кто-нибудь объяснить на простом примере, как ниже, где позднее связывание выгодно и почему кто-то должен выбрать это по раннему связыванию?
Хорошо, я собираюсь пропустить весь вопрос определения «раннее связывание против позднего связывания» и делать вид, что вы спросили: «Почему кто-то использует указатели на функции вместо оператора 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);
}
}
Это красиво и функционально. Но это не гибкий. Зачем? Потому что все функции, которые могут быть вызваны, определяются 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);
}
Теперь, если вы хотите добавить больше операций, просто вставьте элементы в funcs
, Если InvokeOperation
были частью какой-то библиотеки, у вас не было бы права менять ее. Со статическим связыванием у вас будет негибкая система; то, что он поддерживает, то, что он будет всегда служба поддержки.
С помощью динамического связывания вы можете добавлять все, что захотите, независимо от того, имеете ли вы право изменять библиотеку напрямую или нет.
Других решений пока нет …