【问题标题】:Polymorphism: Accessing derived member function from base pointer多态性:从基指针访问派生成员函数
【发布时间】:2018-08-20 22:18:18
【问题描述】:

鉴于以下情况:

#include <vector>

struct Widget
{
    void doThing()
    {
       ...
    }
};

struct SpecialWidget : public Widget
{
    void doSpecialThing()
    {
        ...
    }
};

int main()
{
    std::vector<Widget*> widgets;
    widgets.push_back(new Widget());
    widgets.push_back(new SpecialWidget());
    ...

    for(auto& w : widgets)
    {
        w->doThing();
        //Also need to call doSpecialThing() if element is a SpecialWidget
    }

    return 0;
}

在这里将doSpecialThing() 声明为基类Widget 中的虚函数并让它什么都不做是正确的吗?我相当肯定答案是否定的。在哪种情况下,有没有更好的方法来解决这个问题?

亲切的问候

【问题讨论】:

  • 你想要SpecialWidgetdoSpecialThing() 而不是doThing()?如果是这样,只需覆盖doThing()。如果您想要 doSpecialThing()doThing() 和其他东西,请再次覆盖并事先明确调用 Widget::doThing()

标签: c++ inheritance polymorphism


【解决方案1】:

虚函数应该总是在基类中。在不是基类的任何类中添加 virtual 关键字不会有任何效果。

我们还可以通过显式指定相关函数的范围来调用函数的基类版本。

如果您可以将 doSpecialThing 更改为 doThing,您的代码可以简单地变成:

struct Widget
{
    //make virtual for dynamic function binding with Widget pointers
    virtual void doThing()
    {
       ...
    }
};

struct SpecialWidget : public Widget
{
    void doThing()
    {
        Widget::doThing();
        ...
    }
};

或者如果你想保留它为doSpecialThing:

struct Widget
{
    //make virtual for dynamic function binding with Widget pointers
    virtual void doThing()
    {
       ...
    }
};

struct SpecialWidget : public Widget
{
    void doThing() {
        Widget::doThing(); 
        doSpecialThing();
    }

    void doSpecialThing()
    {
        ...
    }
};

【讨论】:

    【解决方案2】:

    您有一堆不同的函数名称正在互换,但据我所知,您希望派生类调用它自己的 doThing(),然后让基类调用它自己的 doThing(),这是完全可以接受的.

    #include <vector>
    
     struct Widget{
         virtual void doThing()
         {
             cout << "Base"  << endl;
         }
     };
    
     struct SpecialWidget : public Widget
     {
         void doThing()
         {
             cout << "Derived" << endl;
             Widget::doThing();
         }
     };
    

    虽然我对我的 C++ 有点生疏,但我相信这会起作用,但输出会是

    Derived
    Base
    

    【讨论】:

      【解决方案3】:

      作为我评论的扩展,如果您希望 SpecialWidget 与基本 doThing() 一起做一些特别的事情,更好的方法是在 SpecialWidget 中覆盖 doThing(),如下所示:

      struct SpecialWidget : public Widget
      {
          void doThing()
          {
              Widget::doThing();
              ...
          }
      };
      

      并照常调用其他所有内容。

      【讨论】:

        猜你喜欢
        • 2013-12-09
        • 2011-01-27
        • 1970-01-01
        • 2011-08-23
        • 2016-07-31
        • 1970-01-01
        • 2021-08-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多