Виртуальная функция базового класса принудительной вызовы
У меня есть такие события, как этот
class Granpa // this would not be changed, as its in a dll and not written by me
{
public:
virtual void onLoad(){}
}
class Father :public Granpa // my modification on Granpa
{
public:
virtual void onLoad()
{
// do important stuff
}
}
class Child :public Father// client will derive Father
{
virtual void onLoad()
{
// Father::onLoad(); // i'm trying do this without client explicitly writing the call
// clients code
}
}
Есть ли способ принудительно вызвать onLoad без фактического написания Отца:: onLoad()?
Hackish решения приветствуются:)
Ответы
Ответ 1
Если я правильно понимаю, вы хотите, чтобы всякий раз, когда вызывалась функция overriden, сначала необходимо вызвать вызов базового класса. В этом случае вы можете исследовать шаблон шаблона. Что-то вроде:
class Base
{
public:
void foo() {
baseStuff();
derivedStuff();
}
protected:
virtual void derivedStuff() = 0;
private:
void baseStuff() { ... }
};
class Derived : public Base {
protected:
virtual void derivedStuff() {
// This will always get called after baseStuff()
...
}
};
Ответ 2
Как было предложено выше, но применительно к вашему делу.
class Father :public Granpa // my modification on Granpa
{
public:
virtual void onLoad()
{
// do important stuff
onLoadHandler();
}
virtual void onLoadHandler()=0;
}
class Child :public Father// client will derive Father
{
virtual void onLoadHandler()
{
// clients code
}
}
Однако ничто не может помешать Child переопределить onLoad, так как С++ не имеет конечного ключевого слова, а Granpa onLoad сама по себе является виртуальной.
Ответ 3
Ну, нет широко известного, признанного способа сделать это. Если бы это было, библиотеки GUI, использующие события и сигналы, вероятно, внедрили бы это. Однако есть и другие решения вашей проблемы.
Вы можете реализовать соединение сигнала - события, используя boost.Signals, sigslot или что-то вроде вашего собственного создания. Как GTK + делает:
g_signal_connect(my_wdg, "expose-event", G_CALLBACK(my_func), NULL);
gboolean my_func(...)
{
// do stuff
return FALSE; /* this tells the event handler to also call the base class slot */
}
Менее C-центричным способом это может быть реализовано в следующих строках:
/* In Granpa */
/* typedef a functor as 'DerivedEventHandler' or use a boost::function */
std::vector< DerivedEventHandler > handlers;
void connect(DerivedEventHandler event) { handlers.push_back(event); }
/* in loop */
while (! iter = handlers.end() ) /* call event */
/* In constructor of Father */
this->connect( this->OnLoad );
/* In constructor of Child */
this->connect( this->OnLoad );
/* and so on... in all derived classes */
Ответ 4
Если объект, о котором идет речь, является небольшим и дешевым для копирования, просто вызовите конструктор копирования базового класса, то есть BaseClass (* производный_class_object).method()