Переопределение перегруженной функции основы в C++ [дубликат]

Посмотрите на функции position(), count() и last(); например, test="position() < last()".

47
задан Community 23 May 2017 в 10:34
поделиться

3 ответа

В панели классов добавьте

using foo::a;

. Это обычная ошибка в C ++. Как только совпадение имени найдено в области класса a, он не ищет перегрузок по дереву наследования. Задавая объявление using, вы переносите все перегрузки a из foo в область действия bar. Тогда перегрузка работает правильно.

Помните, что если существует код, использующий класс 'foo', его значение может быть изменено дополнительными перегрузками. Или дополнительные перегрузки могут внести двусмысленность, и код не будет скомпилирован. На это указывает ответ Джеймса Хопкина.

72
ответ дан 26 November 2019 в 19:31
поделиться

Именно так работал язык. До с использованием ключевого слова , если вы переопределяли одну перегруженную функцию, вам приходилось перегружать их все:

class bar : public foo 
{
  public:
    bar(void);
    ~bar(void);
    a(int);
    a(double d) { foo::a(d); }  // add this
}

Это настолько раздражало людей, что языковой комитет добавил , используя функцию , но некоторые Старые привычки умирают с трудом; и у постоянных посетителей есть веские аргументы.

Как указывает Джеймс Хопкинс, добавляя с помощью , программист выражает намерение, что производный класс без предупреждения добавит любые будущие переопределения foo: : a () в список допустимых подписей.

Вот пример того, что он описывает:

#include <iostream>
class Base {
public:
  virtual void f(double){ std::cout << "Base::Double!" << std::endl; }
  // virtual void f(int) { std::cout << "Base::Int!" << std::endl; } // (1)
  virtual ~Base() {}
};

class Derived : public Base {
public:
  // using Base::f; // (2)
  void f(double) { std::cout << "Derived::Double!" << std::endl; }
};

int main(int, char **) {
  Derived d;
  d.f(21);
  return 0;
}

Результатом будет "Derived :: Double!" потому что компилятор преобразует целочисленный аргумент в двойной. g ++ 4.0.1 -Wall не будет предупреждать о том, что это продвижение произошло.

Раскомментируйте (1), чтобы смоделировать будущие изменения в Base, добавив метод Base :: f (int). Код компилируется, опять же без предупреждения, даже с -Wall и "Derived :: Double!" остается выходом.

Теперь раскомментируйте (2), чтобы смоделировать решение производного программиста включить все сигнатуры Base :: f. Код компилируется (без предупреждений), но теперь на выходе получается «Base :: Int!».

-

† Я не могу придумать английского слова для обозначения «те, у кого есть привычка», а «зависимый» - это много слишком сильно.

21
ответ дан 26 November 2019 в 19:31
поделиться

Это сделано специально. Разрешение перегрузки ограничено одной областью. Это предотвращает некоторые неприятные случаи изменения значения допустимого кода при добавлении дополнительных функций к базовому классу или в область видимости пространства имен.

12
ответ дан 26 November 2019 в 19:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: