Недавно я столкнулся с поведением в С++ относительно указателей на функции, которые я не могу полностью понять. Я попросил Google помочь, а также некоторые из моих более опытных коллег, но даже они не могли помочь.
Следующий код демонстрирует это мистическое поведение:
class MyClass{
private:
int i;
public:
MyClass(): i(0) {}
MyClass(int i): i(i) {}
void PrintText() const { std::cout << "some text " << std::endl;}
};
typedef void (*MyFunction) (void*);
void func(MyClass& mc){
mc.PrintText();
}
int main(){
void* v_mc = new MyClass;
MyFunction f = (MyFunction) func; //It works!
f(v_mc); //It works correctly!!!
return 0;
}
Итак, сначала я определяю простой класс, который будет использоваться позже (особенно, его метод-член PrintText
). Затем я определяю объект name void (*) (void*)
как MyFunction
- указатель на функцию с одним параметром void*
и не возвращает значение.
После этого я определяю функцию func()
, которая принимает ссылку на объект MyClass
и вызывает свой метод PrintText
.
И наконец, магия происходит в основной функции. Я динамически выделяю память для нового объекта MyClass
, который возвращает возвращаемый указатель на void*
. Затем я навел указатель на функцию func()
на указатель MyFunction
- я не ожидал, что это вообще скомпилируется, но это произойдет.
И, наконец, я называю этот новый объект аргументом void*
, хотя базовая функция (func()
) принимает ссылку на объект MyClass
. И все работает правильно!
Я попытался скомпилировать этот код с Visual Studio 2010 (Windows) и XCode 5 (OSX), и он работает одинаково - никаких предупреждений не сообщается. Я предполагаю, что причина этого в том, что ссылки на С++ фактически реализованы как указатели за кулисами, но это не объяснение.
Я надеюсь, что кто-то сможет объяснить это поведение.