В каких случаях используются операторы x.*ptm
или p->*ptm
? Прошу привести минимальный пример, где это может понадобиться. Да и вообще, где это реально может пригодится. Стоит ли использовать их? Можно ли их чем нибудь заменить?
Вызывать подобным образом методы приходится ровно в том случае, если Вы сохранили указатель на этот метод :) Как это работает, описал @Harry, а вот зачем - это хороший вопрос.
Нередко возникает ситуация, когда программисты хотят упростить себе жизнь (ленивые же). Написали Вы, например, такой код:
#include <iostream>
enum class State {
One, Two, Three
};
class A {
State _cur_state;
public:
A(State s) : _cur_state(s) {}
void DoSomething() {
switch (_cur_state) {
case State::One:
std::cout << "Foo" << std::endl;
break;
case State::Two:
std::cout << "Bar" << std::endl;
break;
case State::Three:
std::cout << "Baz" << std::endl;
break;
}
};
};
int main() {
A(State::One).DoSomething();
}
Через некоторое время придёт осознание того, что проще-таки написать
class A {
State _cur_state;
public:
A(State s) : _cur_state(s) {}
void DoSomething() {
static std::unordered_map<State, std::string> state_to_string {
{ State::One, "Foo" },
{ State::Two, "Bar" },
{ State::Three, "Baz" }
};
std::cout << state_to_string[_cur_state] << std::endl;
};
};
Через некоторое время оказывается, что в case
ах должен быть какой-то замудреный код и Вы возвращаетесь к первоначальному варианту, переместив этот код в методы:
class A {
State _cur_state;
void DoFoo() { /* code */ }
void DoBar() { /* code */ }
void DoBaz() { /* code */ }
public:
A(State s) : _cur_state(s) {}
void DoSomething() {
switch (_cur_state) {
case State::One:
DoFoo();
break;
case State::Two:
DoBar();
break;
case State::Three:
DoBaz();
break;
}
};
};
Но потом Вы вспоминаете про указатели на методы и код вновь становится чистым!
class A {
State _cur_state;
void DoFoo() { /* code */ }
void DoBar() { /* code */ }
void DoBaz() { /* code */ }
public:
A(State s) : _cur_state(s) {}
void DoSomething() {
static std::unordered_map<State, void(A::*)()> state_to_method {
{ State::One, &A::DoFoo },
{ State::Two, &A::DoBar },
{ State::Three, &A::DoBaz }
};
(this->*state_to_method[_cur_state])();
};
};
P.S. Обработку ошибок не писал.
P.P.S. В случае enum
ов быстрее будет вариант с вектором или первоначальный, но данный пример для академических целей.
Ну, например, у вас есть функция, которая должна вызвать определенную функцию-член определенного объекта - все определяется во время работы.
class Test {
int m;
public:
Test(int i = 0):m(i){}
void func1() const { cout << "Test::func1, m = " << m << "\n"; }
void func2() const { cout << "Test::func2, m = " << m << "\n"; }
};
// Тип testfunc - указатель на функцию-член Test
typedef void (Test::*testfunc)() const;
// Вызов для объекта Test функции f
void out(const Test& t, testfunc f)
{
(t.*f)();
}
// То же через указатель
void outPtr(const Test* t, testfunc f)
{
(t->*f)();
}
int main() {
Test a(1), b(2);
out(a,&Test::func1);
out(b,&Test::func2);
outPtr(&a,&Test::func2);
outPtr(&b,&Test::func1);
}
Рабочий пример тут.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
ЗдравствуйтеКто знает, почему в этом проэкте две ошибки? "invalid conversion from 'int()(const char)' to 'const void*' [-fpermissive]"
Я создаю вектор ссылок на объекты моего класса в главной функции - всё работает замечательноСоздаю схожий вектор в ином классе - всё работать...
Как это правильно реализовать, чтобы захват был в Mat?