РЕДАКТИРОВАТЬ: я ограничен C ++ 03 по этой теме.
В следующем коде класс Impl
происходит от Intf
и содержит экземпляр класса Caller
.
Ctor
Caller
принимает экземпляр Intf::
и указатель на функцию-член;он вызывает последний для первого в Caller::func()
.
Impl
ctor регистрирует себя и свою функцию-член func()
со своим экземпляром Caller
.
Я хотел бычтобы Impl
содержал несколько Caller
экземпляров и регистрировал разные указатели на функции-члены с каждым экземпляром, чтобы при вызове каждого содержащегося Caller
экземпляра ::func()
получалась другая вызываемая функция-член Impl
- это можно сделать?1023 *
Единственный способ сделать это - определить несколько чисто виртуальных функций в Intf
, реализовать их в Impl
и зарегистрировать эти переопределяющие функции.Но это не идеальное решение для меня: я хотел бы знать, есть ли способ зарегистрировать разные указатели на функции-члены с разными экземплярами регистрирующего класса без создания виртуальных функций в классе интерфейса 1: 1 с переопределением функций в реализующем классе.
Мне нужно исключить возможность Caller
взятия ссылки Impl
и функции-члена;Caller
может знать только о Intf
с, а не Impl
с.
// main.cpp
#include <iostream>
class Intf
{
public:
virtual void func() = 0;
typedef void (Intf::*funcPtr)();
};
class Caller
{
public:
Caller( Intf& f, Intf::funcPtr func ) : f_( f ), func_( func ) {}
void func() { f_.func(); }
private:
Intf& f_;
Intf::funcPtr func_;
};
class Impl : public Intf
{
public:
Impl()
: c_ ( *this, &Intf::func )
// , c2_( *this, static_cast<Intf::funcPtr>(func2) )
{
}
void callCaller() { c_.func(); };
// void callCaller2() { c2_.func(); };
private:
void func()
{
std::cout << __FUNCTION__ << std::endl;
}
void func2()
{
std::cout << __FUNCTION__ << std::endl;
}
Caller c_;
// Caller c2_;
};
int main( int argc, char* argv[] )
{
Impl i;
i.callCaller();
return 0;
}
Дополнительный вопрос: кто-то может объяснить, почему в ctor Impl
необходимо указывать указательдля функции-члена func()
с Intf::
?Т.е. почему это правильно ...
Impl() : c_ ( *this, &Intf::func ) {}
... и почему это не правильно ...
Impl() : c_ ( *this, &Impl::func ) {}
Impl() : c_ ( *this, &func ) {}
?
Ошибка компилятора вПример версии & & Impl :: func:
g ++ -g main.cpp && ./a.out
main.cpp: In constructor 'Impl::Impl()':
main.cpp:31:31: error: no matching function for call to 'Caller::Caller(Impl&, void (Impl::*)())'
: c_ ( *this, &Impl::func )
^
main.cpp:31:31: note: candidates are:
main.cpp:16:3: note: Caller::Caller(Intf&, Intf::funcPtr)
Caller( Intf& f, Intf::funcPtr func ) : f_( f ), func_( func ) {}
^
main.cpp:16:3: note: no known conversion for argument 2 from 'void (Impl::*)()' to 'Intf::funcPtr {aka void (Intf::*)()}'
main.cpp:12:7: note: Caller::Caller(const Caller&)
class Caller
^
main.cpp:12:7: note: candidate expects 1 argument, 2 provided
Ошибка компилятора ввариант версии & & func:
>g++ -g main.cpp && ./a.out
main.cpp: In constructor 'Impl::Impl()':
main.cpp:31:20: error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function. Say '&Impl::func' [-fpermissive]
: c_ ( *this, &func )
^
main.cpp:31:25: error: no matching function for call to 'Caller::Caller(Impl&, void (Impl::*)())'
: c_ ( *this, &func )
^
main.cpp:31:25: note: candidates are:
main.cpp:16:3: note: Caller::Caller(Intf&, Intf::funcPtr)
Caller( Intf& f, Intf::funcPtr func ) : f_( f ), func_( func ) {}
^
main.cpp:16:3: note: no known conversion for argument 2 from 'void (Impl::*)()' to 'Intf::funcPtr {aka void (Intf::*)()}'
main.cpp:12:7: note: Caller::Caller(const Caller&)
class Caller
^
main.cpp:12:7: note: candidate expects 1 argument, 2 provided