Мы можем фактически выполнить все 3 ваших funcPointer*
с в C ++ 11 с появлением bind
и лямбда-функций . Давайте сначала поговорим о каждом и обсудим, что они делают:
funcPointer
стремится вызвать метод Child
без объекта Child
, поэтому объект Child
должен быть сохранен. Дочерний объект может быть сохранен указателем: bind(&Child::TestFunc, this)
Или в C ++ 14 он может быть сохранен по значению: [arg = *this]() mutable { arg.TestFunc(); }
funcPointer2
стремится вызвать метод Child
с Parent*
. Мы можем сделать это следующим образом: [](Parent* arg){ static_cast<Child*>(arg)->TestFunc(); }
Конечно, это не будет более законным, чем (new Parent)->TestFunc()
, поэтому мы предполагаем, что Parent*
на самом деле Child*
, если вы готовы сделать Parent
Полиморфный тип , который вы можете проверить, прежде чем позвонить в свою лямбду:
[](Parent* arg) {
assert(dynamic_cast<Child*>(arg) != nullptr);
static_cast<Child*>(arg)->TestFunc();
}
funcPointer3
стремится сохранить указатель на метод Child
, и у вас это уже работает. Вам просто нужно было использовать Child
объект для его вызова, например: (this->*p.funcPointer3)()
. Но вы должны назначить funcPointer3
следующим образом: funcPointer3 = &Child::TestFunc
, потому что если вы попытаетесь сделать это: funcPointer3 = &TestFunc
, вы получите ошибку:
'&': недопустимая операция с выражением функции связанного члена
Далее, указатель на функцию или указатель на функцию-член не может использоваться для ссылки на Тип закрытия , поэтому нам нужно будет преобразовать ваши указатели функций в function
объекты. (funcPointer3
- это просто указатель на функцию-член, поэтому его не нужно преобразовывать, но я преобразую его, чтобы продемонстрировать, что function
объект может содержать член указатель на функцию, и это упрощает вызов: p.funcPointer(this)
):
class Parent {
public:
function<void()> funcPointer;
function<void(Parent*)> funcPointer2;
function<void(Child*)> funcPointer3;
};
Теперь, когда мы адаптировали Parent
, мы можем легко назначить, как показано в 1 , 2 и 3 :
void Child::Do() {
Parent p;
p.funcPointer = bind(&Child::TestFunc, this);
p.funcPointer2 = [](Parent* arg) { static_cast<Child*>(arg)->TestFunc(); };
p.funcPointer3 = &Child::TestFunc;
p.funcPointer();
p.funcPointer2(this);
p.funcPointer3(this);
}
Вы, наверное, знаете это и просто тестировали, но мы могли бы так же легко использовать элементы Parent
, от которых Child
унаследовали, как мы могли бы создать новый объект Parent
в Child::Do
. Я собираюсь переключить это и бросить код в примере: http://ideone.com/yD7Rom