Недавно я столкнулся с поведением в С++ относительно указателей на функции, которые я не могу полностью понять. Я попросил 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), и он работает одинаково - никаких предупреждений не сообщается. Я предполагаю, что причина этого в том, что ссылки на С++ фактически реализованы как указатели за кулисами, но это не объяснение.
Я надеюсь, что кто-то сможет объяснить это поведение.