从基类解析C ++虚函数

时间:2010-02-27 16:31:38

标签: c++ inheritance virtual-functions

很抱歉,如果这是一个骗局,我无法找到答案。

我想从基类成员调用一个函数,并让它解析为子类版本。我认为宣布虚拟会做到这一点,但事实并非如此。这是我的方法:

class GUIWindow
{
public:
    GUIWindow()
    {
        SetupCallbacks();
    }

    virtual void SetupCallbacks()
    {
         // This function always called
    }
};

class GUIListbox : public GUIWindow
{
public:
    void SetupCallbacks()
    {
        // This never called
    }
};

GUIListbox lb; // GUIWindow::SetupCallbacks is called :(

我做错了什么?

非常感谢

的Si

5 个答案:

答案 0 :(得分:8)

答案 1 :(得分:3)

在构建某个类C期间调用虚函数时(即C的构造函数处于活动状态时),虚拟机制正常工作,但它在< em>受限模式。类层次结构中虚拟调用的解析由当前正在构造的类(C限制。这意味着虚拟调用将解析为类C是层次结构中的“最终”类,就好像它没有后代一样。

析构函数也是如此。

在您的示例中,您正在从类GUIWindow的构造函数中调用虚函数。只要GUIWindow的构造函数处于活动状态,其虚拟机制就会像从GUIWindow派生的其他类一样工作。这种机制将完全忽略GUIListbox类的存在。这就是为什么虚拟呼叫的解决方案在GUIWindow“停止”并调用GUIWindow::SetupCallbacks,就好像GUIListbox::SetupCallbacks不存在一样。

您可以在C ++ FAQ中阅读 http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.5

答案 2 :(得分:1)

您的派生类型尚未构建。

Class Cat : Animal
{
//...
};

创建Cat对象时,会发生以下情况:

  1. 构建动物
  2. 构建Cat
  3. 如果您的对象超出范围,或者如果在堆上通过删除而被销毁,则会发生以下情况:

    1. Destruct Cat
    2. Destruct Animal
    3. 因此,您不应在构造函数或析构函数中调用虚函数。如果您的基类中没有实现,您甚至可以拥有pure virtual function call

      你将不得不:

      GUIListbox lb;
      lb.SetupCallbacks();
      

      虚拟的目的是让你可以做以下事情:

      GuiWindow *lb = new GuiListbox();
      lb->SetupCallback();//Gets correctly resolved to GuiListBox's version
      

答案 3 :(得分:0)

问题是你试图从构造函数中调用虚函数。基类构造函数在派生类的构造函数之前调用,因此在基类构造函数运行时,尚未创建对象的“派生部分”。

对象的行为类似于基类类型的对象,直到基类构造函数完成并且派生类构造函数启动。这意味着对虚函数的调用不会调用派生类中定义的实现,它们只会从基类执行该版本。

另请参阅more detailspossible workarounds的C ++ FAQ lite。

答案 4 :(得分:-1)

快速回答是您可能必须在GUIListbox中声明一个调用SetupCallbacks的构造函数。原因更复杂:因为GUIListbox没有声明构造函数,当您声明该类型的对象时,会调用GUIWindow构造函数。当GUIWindow构造函数正在运行时,对象还不是GUIListbox 。从编译器的角度来看,只有当该类的(空)构造函数启动时,它才会成为GUIListbox。因此,当第一个构造函数运行时,将调用GUIWindow中的方法。 IOWs,这不起作用,并且永远不会以你想要的方式在C ++中工作。

这是一个详细描述这个陷阱的参考:http://www.artima.com/cppsource/nevercall.html

以下是我最喜欢的C ++资源的解释:http://yosefk.com/c++fqa/inheritance-mother.html#fqa-23.5