Учитывая следующий сценарий:
#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
и ничего не делать? Я уверен, что ответ - нет. В каком случае, есть ли лучший подход к этой проблеме?
С уважением
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()
{
...
}
};
У вас есть куча разных имен функций, которые вы меняете, но из того, что я понял, вы хотите, чтобы производный класс вызывал собственный 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
В качестве расширения моего комментария, если вы хотите, чтобы SpecialWidget
делал что-то особенное вместе с базой doThing()
, лучшим способом было бы переопределить doThing()
в SpecialWidget
следующим образом :
struct SpecialWidget : public Widget
{
void doThing()
{
Widget::doThing();
...
}
};
И называть все остальное как обычно.
Новые вопросы
c++
C ++ - это язык программирования общего назначения. Первоначально он был разработан как расширение C и имеет аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде (который будет скомпилирован с помощью компилятора C ++). Используйте тег, зависящий от версии, для вопросов, связанных с конкретной редакцией стандарта [C ++ 11], [C ++ 14], [C ++ 17] или [C ++ 20] и т. Д.