Следуя простому правилу для получения через класс шаблона, это возможно.
#include <iostream>
struct TEvent
{
};
struct Base {
virtual void CallOnEvent(TEvent * e)
{
OnEvent(e);
}
virtual void OnEvent(TEvent * e)
{
std::cout << "Base::Event" << std::endl;
}
void CallUp(TEvent * e)
{
}
};
template <typename B>
struct TDerived : public B
{
void CallUp( TEvent * e )
{
B::CallUp(e);
B::OnEvent(e);
}
virtual void CallOnEvent( TEvent * e )
{
CallUp(e);
this->OnEvent(e);
}
};
struct Derived01 : public TDerived< Base >
{
void OnEvent(TEvent * e)
{
std::cout << "Derived01::Event" << std::endl;
}
};
struct Derived02 : public TDerived< Derived01 >
{
void OnEvent(TEvent * e)
{
std::cout << "Derived02::Event" << std::endl;
}
};
struct Derived03 : public TDerived< Derived02 >
{
void OnEvent(TEvent * e)
{
std::cout << "Derived03::Event" << std::endl;
}
};
struct Derived04 : public TDerived< Derived03 >
{
void OnEvent(TEvent * e)
{
std::cout << "Derived04::Event" << std::endl;
}
};
int main( void )
{
Derived04 lD4;
lD4.CallOnEvent(0);
return 0;
}
Этот код дает ( codepad ):
Base::Event
Derived01::Event
Derived02::Event
Derived03::Event
Derived04::Event
Относительно некоторыхответы с использованием typeid
.Я бы никогда не подумал об использовании typeid
для чего-то еще, кроме отладки.Это связано с двумя причинами:
- динамическая проверка типов может быть выполнена гораздо более эффективными способами (без создания
type_info
объекта, то есть с использованием dynamic_cast
, некоторые методы - C ++Стандарт в основном гарантирует только наличие typeid, но не совсем то, как он работает (большинство вещей «зависит от компилятора»)
edit:
Aнемного более сложный пример с множественным наследованием. Этот, к сожалению, невозможно решить без явных вызовов в классах, которые наследуются от нескольких баз (в основном потому, что неясно, что должно происходить в таких случаях, поэтому мы должны явно определить поведение).
#include <iostream>
struct TEvent
{
};
struct Base {
virtual void CallOnEvent(TEvent * e)
{
OnEvent(e);
}
virtual void OnEvent(TEvent * e)
{
std::cout << "Base::Event" << std::endl;
}
void CallUp(TEvent * e)
{
}
};
template <typename B >
struct TDerived : public B
{
void CallUp( TEvent * e )
{
B::CallUp(e);
B::OnEvent(e);
}
virtual void CallOnEvent( TEvent * e )
{
CallUp(e);
this->OnEvent(e);
}
};
struct Derived01 : virtual public TDerived< Base >
{
void OnEvent(TEvent * e)
{
std::cout << "Derived01::Event" << std::endl;
}
};
struct Derived02 : virtual public TDerived< Derived01 >
{
void OnEvent(TEvent * e)
{
std::cout << "Derived02::Event" << std::endl;
}
};
typedef TDerived< Derived02 > TDerived02;
typedef TDerived< Derived01 > TDerived01;
struct Derived03 : virtual public TDerived02, virtual public TDerived01
{
void OnEvent(TEvent * e)
{
std::cout << "Derived03::Event" << std::endl;
}
virtual void CallOnEvent( TEvent * e )
{
CallUp(e);
Derived03::OnEvent(e);
}
void CallUp( TEvent * e )
{
TDerived02::CallUp(e);
TDerived01::CallUp(e);
}
};
struct Derived04 : public TDerived< Derived03 >
{
void OnEvent(TEvent * e)
{
std::cout << "Derived04::Event" << std::endl;
}
};
int main( void )
{
Derived04 lD4;
Derived03 lD3;
lD3.CallOnEvent( 0 );
std::cout << std::endl;
lD4.CallOnEvent( 0 );
return ( 0 );
}
Результат ( ideone ):
Base::Event \ \
Derived01::Event | - from Derived02 |
Derived02::Event / |-- from Derived03
Base::Event \__ from Derived01 |
Derived01::Event / |
Derived03::Event /
Base::Event \ \ \
Derived01::Event | - from Derived02 | |
Derived02::Event / |-- from Derived03 |-- from Derived04
Base::Event \__ from Derived01 | |
Derived01::Event / | |
Derived03::Event / |
Derived04::Event /