Учитывая следующий сценарий:

#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 и ничего не делать? Я уверен, что ответ - нет. В каком случае, есть ли лучший подход к этой проблеме?

С уважением

1
not an alien 21 Авг 2018 в 01:18

3 ответа

Лучший ответ

Виртуальные функции всегда должны быть в базовом классе. Добавление ключевого слова 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()
    {
        ...
    }
};
3
scohe001 20 Авг 2018 в 22:37

У вас есть куча разных имен функций, которые вы меняете, но из того, что я понял, вы хотите, чтобы производный класс вызывал собственный 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
0
vividpk21 20 Авг 2018 в 22:30

В качестве расширения моего комментария, если вы хотите, чтобы SpecialWidget делал что-то особенное вместе с базой doThing(), лучшим способом было бы переопределить doThing() в SpecialWidget следующим образом :

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

И называть все остальное как обычно.

0
Major 20 Авг 2018 в 22:30
51939217