<...>>
АТ>>Указатель на функцию одного класса в С++ можно приводить к указателю на функцию любого другого класса при помощи 'reinterpret_cast'.
А>Т.е. это проблемы MSVC, что у него указатель на функцию-член бывает всех размеров — от 4 до 12, и зависит от вируальности функции и наследования ?
И да, и нет. Разноразмерные указатели у MSVC бывают при умолчатеьных установках проекта: модель указателя на член класса = 'Best case always'. Зайди в установки проекта и явно включи более общую модель указателя на член класса — и все станет в порядке.
Не так всё просто. Там же сначала кастуется к указателю на член Thunk, а потом прямо так и вызывается, как метод Thunk. Информация о типе Owner уже потеряна, так что даже для универсального представления указателей вызов теоретически может быть неверным. В любом случае это неправильно — преобразовывать указатели на члены друг в друга. Это борьба с системой типов, которая выходит боком.
Здравствуйте, Viktor Sazhaev, Вы писали:
VS>Не так всё просто. Там же сначала кастуется к указателю на член Thunk, а потом прямо так и вызывается, как метод Thunk. Информация о типе Owner уже потеряна, так что даже для универсального представления указателей вызов теоретически может быть неверным. В любом случае это неправильно — преобразовывать указатели на члены друг в друга. Это борьба с системой типов, которая выходит боком.
Программирования без борьбы не бывает, главное чтобы эта борьба была осознанной. Я почи во всех сових проектах юзаю эту библиотеку и ни разу не прогорел. В реальной жизни в слот передается указатель и функции из одного класса. Согласитесь делать slot в одном классе, а handler в другом (даже в базовом) не есть хороший стиль программирования. Когда slot и handler находтся в одном классе проблем возникнуть не может по определению, независимо от того есть множественное наследование или нет.
Microsoft (R) 32-bit C/C++ Standard Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.
events.cpp
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\sigslot.h(42)
: error C2440: 'type cast' : cannot convert from 'void (__thiscall EventHandler::* )(Arg)' to 'slot::Func'
with
[
Arg=const char *
]
Pointers to members have different representations; cannot cast between them
events.cpp(32) : see reference to function template instantiation
'void slot::init<EventHandler,const char*>(signal<Arg> &,void (__thiscall EventHandler::* )(Arg),Owner *)' being compiled
with
[
Arg=const char *,
Owner=EventHandler
]
Заметь — это последняя версия компилятора (VS.NET2003), VC6, конечно тоже ругается.
Т.е. указатели на разные классы нельзя преобразовывать друг к другу.
Мозно включить (естественно нестандартную) опцию в MSVC, но тогда пропадет оптимизация,
а это же C++ — тут невидимая, но сильная оптимизация есть одно из основных преимуществ языка.
Да даже если бы можно было — все равно был бы вылет:
У тебя в коде указатель на функцию EventHandler::onEvent (который занимает 16 байт) хранится как указатель на
функцию Thunk::f, который занимает 4 байта — очевидно, что это некорректно.
)
более того у тебя явно зашит тип указателя "Owner*", это естественно не самый лучший метод — например
void onEvent( const char *eventName ) const
уже не будет компилиться — лечится заменой "Owner*" добавлением нового шаблонного параметра "class OwnerPtrTy" и
заменой "Owner*" на "OwnerPtrTy", это кстати позволит связывать signal не только с обычными указателями, но и со
"smart-pointer'ами", что в современных программах на C++ нужно не редко.