强制调用基类虚拟函数

Force calling base class virtual function

本文关键字:虚拟 函数 基类 调用      更新时间:2023-10-16

我有一些类似的事件

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解决方案:)

如果我理解正确的话,您希望这样做,无论何时调用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()
        ...
    }
};

如上所述,但适用于您的案例。

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++没有最终关键字,Granpa onLoad本身就是虚拟的。

好吧,没有广为人知、公认的方法可以做到这一点。如果有的话,使用事件和信号的GUI库可能已经实现了它。然而,还有其他解决方案可以解决你的问题。

您可以使用boost实现信号事件连接。信号,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 */
}

以一种不那么以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  */

如果有问题的对象小且复制成本低,只需调用基类的复制构造函数,即BaseClass(*derived_class_object).method()