Страницы

Поиск по вопросам

понедельник, 17 декабря 2018 г.

Доступ к членам класса через .* и ->*

В каких случаях используются операторы x.*ptm или p->*ptm? Прошу привести минимальный пример, где это может понадобиться. Да и вообще, где это реально может пригодится. Стоит ли использовать их? Можно ли их чем нибудь заменить?


Ответ

Вызывать подобным образом методы приходится ровно в том случае, если Вы сохранили указатель на этот метод :) Как это работает, описал @Harry, а вот зачем - это хороший вопрос.
Нередко возникает ситуация, когда программисты хотят упростить себе жизнь (ленивые же). Написали Вы, например, такой код:
#include
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_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_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ов быстрее будет вариант с вектором или первоначальный, но данный пример для академических целей.

Комментариев нет:

Отправить комментарий