Указатели на функции-члены
Существует несколько дубликатов этого, но никто не объясняет, почему я могу использовать переменную-член для хранения указателя (в FOO
) но когда я пытаюсь сделать это с локальной переменной (в закомментированной части BAR
), это незаконно. Кто-нибудь может объяснить это?
#include <iostream>
using namespace std;
class FOO
{
public:
int (FOO::*fptr)(int a, int b);
int add_stuff(int a, int b)
{
return a+b;
}
void call_adder(int a, int b)
{
fptr = &FOO::add_stuff;
cout<<(this->*fptr)(a,b)<<endl;
}
};
class BAR
{
public:
int add_stuff(int a, int b)
{
return a+b;
}
void call_adder(int a, int b)
{
//int (BAR::*fptr)(int a, int b);
//fptr = &BAR::add_stuff;
//cout<<(*fptr)(a,b)<<endl;
}
};
int main()
{
FOO test;
test.call_adder(10,20);
return 0;
}
5 ответов
Когда вы используете указатель на функцию-член, вам нужно указать объект, на который он действует.
Т.е. вам нужно создать указатель на экземпляр BAR (назовем его bar
) и делать:
(bar->*fptr)(a,b)
чтобы вызвать функцию или экземпляр BAR и сделать:
(bar.*fptr)(a,b)
Перефразируй:
#include <iostream>
class BAR
{
int i;
public:
BAR(): i(0) {};
int AddOne() { return ++i; };
int GetI() { return i; };
}
int main()
{
BAR bar;
auto fPtr = &BAR::AddOne; // This line is C++0x only (because of auto)
std::cout << (bar.*fPtr)(); //This will print 1 to the console
std::cout << std::endl;
std::cout << bar.GetI(); //This will also print 1 to the console.
}
Видимо, вы неправильно понимаете значение this->*
в вызове в FOO
,
Когда вы используете this->*
с участником fptr
указатель this->*
часть не имеет абсолютно никакого отношения к fptr
быть членом FOO
, Когда вы вызываете функцию-член, используя указатель на член, вы должны использовать ->*
оператор (или .*
оператор), и вы всегда должны указывать фактический объект, который вы хотите использовать с указателем на член. Это то, что this->*
часть вызывающего выражения делает. Т.е. звонок всегда будет выглядеть как
(<pointer-to-object> ->* <pointer-to-member>) (<arguments>)
или как
(<object> .* <pointer-to-member>) (<arguments>)
Левая сторона вызова (<pointer-to-object>
или же <object>
выше) не может быть опущено.
Другими словами, не имеет значения, fptr
является переменной-членом, локальной переменной, глобальной переменной или любым другим типом переменной, вызов через fptr
всегда будет выглядеть как
(this->*fptr)(a, b);
при условии, что вы хотите вызвать его с *this
объект. Если, для другого примера, вы хотите вызвать его для другого объекта, на который указывает указатель pfoo
вызов будет выглядеть следующим образом
FOO *pfoo;
...
(pfoo->*fptr)(a, b);
В вашем BAR
класс вызов должен выглядеть как (this->*fptr)(a,b)
даже если fptr
является локальной переменной
Я не думаю, что использование самой переменной является незаконным. Недопустимо пытаться вызвать этот метод без экземпляра класса.
То есть ты должен действительно позвонить (someVar->*fptr)(a,b)
где someVar
имеет тип BAR*
BAR::call_adder()
была пара проблем. Например, вы смешивали дело. В C++ регистр имеет значение. BAR
а также bar
не то же самое. Во-вторых, вы исправили и правильно указали указатель после исправления проблем с регистром, но когда вы пытаетесь вызвать указатель на функцию-член, вам нужно использовать operator ->*
с объектом класса. Вот call_adder()
фиксированный
void call_adder(int a, int b)
{
int (BAR::*fptr)(int a, int b);
fptr = &BAR::add_stuff;
cout<<(this->*fptr)(a,b)<<endl;
}
Когда вы вызываете функцию-член класса, компилятор генерирует код для установки 'this' во время выполнения функции. Когда вы вызываете его из указателя на функцию, это еще не сделано. Есть способы обойти это, но они не "гарантированно" работают и зависят от компилятора. Вы можете делать это, пока вы осторожны и знаете возможные проблемы, с которыми вы можете столкнуться.