вторник, 14 октября 2008 г.

explicit override

Чисто виртуальные классы часто используются для передачи callback-интерфейсов между DLL и EXE. Типичный интерфейсный класс выглядит так:
struct IServerCallback {
virtual void OnStart() =0;
virtual void OnStop() =0;
virtual void OnInfo( void* ptr, long cookie ) =0;
}


Тогда мы у себя создаем реализацию, например так:
class CApplication: public IServerCallback {
CApplication();
virtual ~CApplication();

// Some additional functions
// ...

// IServer callback implemetaion
virtual void OnStart();
virtual void OnStop();
virtual void OnInfo( void* ptr, long cookie );
}


Так вот пока что все в порядке. Но иногда находятся нехорошие люди, которые делают интерфейс не полностью виртуальным, а делают пустую реализацию для некоторых функций. Выяснение причин, почему так происходит, выходит за рамки этой статьи. Выглядит тогда callback-интерфейс, например, так:
struct IServerCallback {
virtual void OnStart() =0;
virtual void OnStop() =0;
virtual void OnInfo( void* ptr, long cookie ) {};
}


И все бы хорошо, пока мы случайно не ошибемся в определении функции. Можно ошибиться в названии или написать const void* ptr вместо void* ptr — не суть. А главное в том, что получим неожиданное поведение — наша функция не будет вызываться. Чтобы избежать этого, можно использовать так называемое explicit override. Как следует из названия, нужно просто явно указать какому интерфейсу принадлежит та или иная функция. Выглядеть это будет так:
class CApplication: public IServerCallback {
CApplication();
virtual ~CApplication();

// Some additional functions
// ...

// IServer callback implemetaion
virtual void IServerCallback::OnStart();
virtual void IServerCallback::OnStop();
virtual void IServerCallback::OnInfo( void* ptr, long cookie );
}


Тут, в случае наличия реализации по умолчанию, компилятор выдаст ошибку, что и требовалось. Ошибка будет и в случае, если декларация функции в интерфейсе и в классе различаются.

UPD: Это работает только в компиляторе от Microsoft и не является стандартом.
UPD: В Microsoft, как я и предполагал, ввели данный синтаксис в Managed C++ для явной реализации интерфейсов(подробнее). Но, оказалось, что это частично можно применять в обычном С++.

Комментировать в ВКонтакте