Быстрые делегаты C++ - Сходства и различия
ОГЛАВЛЕНИЕ
Страница 8 из 12
Сходства и различия
typedef fd::delegate1 < void, int > MyDelegate;
CBase1 b1, b2; CDerived1 d1("d1");
// ----------------------------------------------------------------------
MyDelegate dg1(&CBase1::foo, &b1);
MyDelegate dg2 = &::hello;
if(dg1 == dg2)
cout << "dg1 equals to dg2" << endl;
else
cout << "dg1 does not equal to dg2" << endl;
if(dg1 > dg2)
{
cout << "dg1 is greater than dg2" << endl;
dg1(123);
}
else if(dg1 < dg2)
{
cout << "dg2 is greater than dg1" << endl;
dg2(234);
}
// ----------------------------------------------------------------------
MyDelegate dg3 = dg1;
MyDelegate dg4(&CBase1::foo, &b2);
// указатель функции и связанный с ним указатель вызываемого объекта,
// сохраняемые в dg1, совпадают с теми, которые сохраняются в dg3
if(0 == dg1.compare(dg3))
{ // эта проверка возвращает истину
dg3(345);
}
if(0 == dg1.compare(dg3, true))
{ // эта проверка также возвращает истину
dg3(456);
}
// ----------------------------------------------------------------------
// указатель функции, сохраненный в dg1, совпадает с сохраненным в dg4,
// но связанные с ними указатели на вызываемый объект не совпадают
if(0 == dg1.compare(dg4))
{ // эта проверка возвращает истину
dg4(567);
}
if(0 == dg1.compare(dg4, true))
{ // эта проверка возвращает ложь
dg4(678);
}
// ----------------------------------------------------------------------
if(dg2 != 0)
{ // эта проверка возвращает истину
cout << "dg2 is not empty" << endl;
}
if(dg2)
{ // эта проверка возвращает истину
cout << "dg2 is not empty" << endl;
}
if(!!dg2)
{ // эта проверка возвращает истину
cout << "dg2 is not empty" << endl;
}
if(!dg2.empty())
{ // эта проверка возвращает истину
cout << "dg2 is not empty" << endl;
}
// ----------------------------------------------------------------------
dg1.swap(dg2);
MyDelegate(dg2).swap(dg1); // dg1 = dg2;
MyDelegate().swap(dg1); // dg1.clear();
dg2.clear();
dg3 = 0;
// ----------------------------------------------------------------------
if(dg3.empty())
{
try
{
dg3(789);
}
catch(std::exception & e) { cout << e.what() << endl; }
//исключение 'вызов пустого делегата'
}
// ----------------------------------------------------------------------
CBase1 * pBase = 0;
// намеренное связывание нулевого вызываемого объекта
dg3.bind(&CBase1::foo, pBase);
try
{
FD_ASSERT( !dg3.empty() );
dg3(890);
}
// исключение 'вызов функции-члена при отсутствующем объекте'
catch(std::exception & e) { cout << e.what() << endl; }
Сравнение двух делегатов означает сравнение адреса ячейки памяти, сохраненного внутри указателя функции, и это на самом деле не означает ничего особенного. Но это позволяет использовать наш делегат в контейнере STL без проблем. Так как это 'быстрый' делегат в 'большинстве' случаев, нам не нужно сильно беспокоиться о снижении производительности при копировании делегата внутрь контейнера STL согласно семантике значений.