Определение области действия при наследовании - C ++

StackOverflow https://stackoverflow.com/questions/1005780

  •  05-07-2019
  •  | 
  •  

Вопрос

Я читал FAQ по C ++ 0x от Страуструпа и застрял на этом коде.Рассмотрим следующий код

struct A
{
    void f(double)
    {
        std::cout << "in double" << std::endl;
    }
};

struct B : A
{
    void f(int)
    {
        std::cout << "in int" << std::endl;
    }
};


int main()
{
    A a; a.f(10.10);  // as expected, A.f will get called
    B b; b.f(10.10);  // This calls b.f and we lose the .10 here
    return 0;
}

Насколько я понимаю, когда тип наследуется, все защищенные и общедоступные члены будут доступны из производного класса.Но, судя по этому примеру, похоже, что я ошибаюсь.Я ожидал, что б.ф будет вызывать базовые классы f.Я получил ожидаемый результат, изменив производный класс следующим образом

struct B : A
{
    using A::f;
    void f(int)
    {
        std::cout << "in int" << std::endl;
    }
};

Вопросы

  1. Почему это не работало в первом коде?
  2. Какой раздел стандарта C ++ описывает все эти правила определения области видимости?
Это было полезно?

Решение

Первый код работает так, как и должен работать c ++.

Разрешение перегрузки соответствует очень сложному набору правил.Из библии Страуструпа на c ++ 15.2.2 "Неоднозначности между функциями из разных базовых классов не разрешаются на основе типов аргументов".

Далее он объясняет использование слова "использование", как вы описали.

Это было дизайнерское решение в языке.

Я склонен следовать книге Страуструпа, а не стандарту, но я уверен, что это там есть.

[Править]

Вот оно (из стандарта):

Глава 13

Когда для одного имени в одной и той же области указаны два или более разных объявления, считается, что это имя перегружено.

А потом:

13.2 Соответствие деклараций

1 Два объявления функций с одинаковыми именами ссылаются на одну и ту же функцию, если они находятся в одной области видимости и имеют эквивалентные объявления параметров (13.1).Функция-член производного класса не в том же объеме, как функция-член тем же именем в базовом классе.

Другие советы

Это потому, что A :: f " скрыто " а не "перегружен" или "переопределено". См:

http://www.parashift.com /c++-faq-lite/strange-inheritance.html#faq-23.9

Найдите разрешение перегрузки . похожий, но не идентичный вопрос .

В C ++ нет перегрузки между областями, область видимости в производных классах не является исключением. (в соответствии с языком программирования C ++)

Для получения дополнительной информации посетите http: //www.research. att.com/~bs/bs_faq2.html#overloadderived

В первом случае метод базового класса 'f' скрыт методом производного класса. В C ++ нет перегрузки между областями; вот почему это не называется. Стандарт C ++ объясняет все правила поиска имен членов в разделе 10.2 Поиск имен членов [class.member.lookup] . НТН

Первая версия кода должна действительно вызывать B :: f. Вы переопределяете символ " f " в структуре "B", поэтому скрывает исходный символ "f" из структуры " A " ;. Это не перегрузка, как может показаться.

Всякий раз, когда компилятор встречает b.f (), он выполняет поиск в " B " структура для символа "f". Он присутствует там, поэтому компилятор решает вызвать B :: f (int), преобразовав double в int. Он не видит необходимости сканировать родительский класс для более подходящей функции ...

Тем не менее, когда вы добавляете "используя A :: f", это является директивой объяснения, чтобы компилятор сканировал родительский класс на наличие символа "f". Теперь в классе B есть две перегруженные функции: для int и для double.

Я также считаю, что вы могли бы написать b.A :: f (), не используя " используя " директива в исходном примере ...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top