Принудительно вызывать виртуальную функцию базового класса - PullRequest
16 голосов
/ 15 марта 2012

У меня есть несколько подобных событий

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 без записи Father :: onLoad () ?

Хакерские решения приветствуются:)

Ответы [ 4 ]

26 голосов
/ 15 марта 2012

Если я правильно понимаю, вы хотите, чтобы при каждом вызове переопределенной функции реализация базового класса всегда вызывалась первой.В этом случае вы можете исследовать шаблон шаблона .Что-то вроде:

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()
        ...
    }
};
3 голосов
/ 15 марта 2012

Ну, нет широко известного, признанного способа сделать это.Если бы это было так, библиотеки 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's slot */
}

Менее С-центрично, это может быть реализовано следующим образом:

/* 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  */
3 голосов
/ 15 марта 2012

Как предложено выше, но применимо к вашему случаю.

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, поскольку в c ++ нет ключевого слова final, а Granpa onLoad сам по себе является виртуальным.

0 голосов
/ 03 февраля 2013

Если рассматриваемый объект небольшой и дешевый для копирования, просто вызовите конструктор копирования базового класса, то есть BaseClass (* производный_класс_объекта) .method ()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...