Указатели функций-членов и наиболее быстрые делегаты C++ - Использование кода
ОГЛАВЛЕНИЕ
Использование кода
Исходный код состоит из реализации FastDelegate (FastDelegate.h) и демонстрационного файла .cpp, поясняющего синтаксис. Чтобы использовать их в MSVC, создайте пустое консольное приложение и добавьте в него два данных файла. В GNU просто наберите "g++ demo.cpp" в командной строке.
Быстрые делегаты будут работать с любой комбинацией параметров, но чтобы заставить их работать в как можно большем числе компиляторов, вы должны указать число параметров при объявлении делегата. Есть максимальный предел в 8 параметров, но его не сложно увеличить. Используется пространство имен fastdelegate. Вся сложность заключена во внутреннем пространстве имен, названном detail.
Fastdelegates могут быть связаны с функцией-членом или со статической (свободной) функцией с помощью конструктора или bind(). По умолчанию они установлены в 0 (null). Их также можно установить в null с помощью clear(). Их можно проверить на равенство null, используя оператор ! или empty().
В отличие от большинства других реализаций делегатов, присутствуют операторы равенства (==, !=). Они будут работать даже в случае наличия встраиваемых функций.
Ниже приведена выдержка из FastDelegateDemo.cpp, показывающая большинство допустимых операций. CBaseClass – это виртуальный базовый класс CDerivedClass. Этот пример только лишь демонстрирует синтаксис.
using namespace fastdelegate;
int main(void)
{
// Поддерживаются делегаты с числом параметров не больше 8.
// Здесь приведен случай функции, не имеющей типа.
// Мы объявляем делегат и присоединяем его к SimpleVoidFunction()
printf("-- FastDelegate demo --\nA no-parameter
delegate is declared using FastDelegate0\n\n");
FastDelegate0 noparameterdelegate(&SimpleVoidFunction);
noparameterdelegate();
// вызываем делегат – при этом вызывается SimpleVoidFunction()
printf("\n-- Examples using two-parameter delegates (int, char *) --\n\n");
typedef FastDelegate2<int, char *> MyDelegate;
MyDelegate funclist[10]; // инициализируются пустые делегаты
CBaseClass a("Base A");
CBaseClass b("Base B");
CDerivedClass d;
CDerivedClass c;
// Связывание с простой функцией-членом
funclist[0].bind(&a, &CBaseClass::SimpleMemberFunction);
// также можно связывать со статическими (свободными) функциями
funclist[1].bind(&SimpleStaticFunction);
// и со статичексими функциями-членами
funclist[2].bind(&CBaseClass::StaticMemberFunction);
// и с постоянными функциями-членами
funclist[3].bind(&a, &CBaseClass::ConstMemberFunction);
// и с виртуальными функциями-членами.
funclist[4].bind(&b, &CBaseClass::SimpleVirtualFunction);
// Можно использовать оператор =. Для статических функций
// fastdelegate выглядит аналогично простому указателю функции.
funclist[5] = &CBaseClass::StaticMemberFunction;
// Если класс производный,
// нужно избегать указателей функций-членов.
// Так же как и .bind(), вы можете применять
// глобальную функцию MakeDelegate().
funclist[6] = MakeDelegate(&d, &CBaseClass::SimpleVirtualFunction);
// Наихудший случай – абстрактная виртуальная функция
// виртуально-производного класса с как минимум одним невиртуальным базовым классом.
// Это очень неясная ситуация, с которой вы вряд ли столкнетесь
// в реальности, но она включена как испытание в предельном режиме.
funclist[7].bind(&c, &CDerivedClass::TrickyVirtualFunction);
// ...Но в таких случаях вы должны использовать базовый класс как
// интерфейс. Следующая строка вызывает точно такую же функцию.
funclist[8].bind(&c, &COtherClass::TrickyVirtualFunction);
// можно выполнять связывание непосредственно с помощью конструктора
MyDelegate dg(&b, &CBaseClass::SimpleVirtualFunction);
char *msg = "Looking for equal delegate";
for (int i=0; i<10; i++) {
printf("%d :", i);
// Операторы ==, !=, <=,<,>, and >= работают
// Они работают даже для встроенных функций.
if (funclist[i]==dg) { msg = "Found equal delegate"; };
// Есть несколько способов проверить, пустой ли делегат
// можно использовать if (funclist[i])
// или if (!funclist.empty())
// или if (funclist[i]!=0)
// или if (!!funclist[i])
if (funclist[i]) {
// Вызов генерирует оптимальный ассемблерный код.
funclist[i](i, msg);
} else {
printf("Delegate is empty\n");
};
}
};