Доминирование (C ++) - Dominance (C++)
в C ++ язык программирования, господство относится к конкретному аспекту C ++ поиск имени в присутствии Наследование. Когда компилятор вычисляет набор объявлений, на которые может ссылаться конкретное имя, объявления в очень предковых классах, в которых "преобладают" объявления менее предковых классов, считаются скрытый для поиска имени. В других языках или контекстах тот же принцип может быть обозначен как "маскировка имени " или же "слежка ".
Алгоритм вычисления поиска имени описан в разделе 10.2 [class.member.lookup] C ++ 11 Стандарт.[1] В описании Стандарта не используется слово «доминирование», предпочтение отдается описанию вещей в терминах наборы деклараций и прячется. Однако в указателе есть запись «доминирование, виртуальный базовый класс», относящаяся к разделу 10.2.
Пример без наследования алмаза
пустота ж(двойной, двойной); // в глобальной областиструктура Бабушка и дедушка { пустота ж(int); пустота ж(двойной, двойной);};структура Родитель : общественный Бабушка и дедушка { пустота ж(int); // скрывает все перегрузки Grandparent :: f};структура Ребенок : общественный Родитель { пустота грамм() { ж(2.14, 3.17); } // преобразуется в Parent :: f};В приведенном выше примере Ребенок :: g содержит ссылку на имя ж. Однако программа в целом содержит четыре объявления имени ж. Чтобы выяснить, какие ж подразумевается, компилятор вычисляет набор перегрузки содержащий все объявления, которые не скрыты в момент вызова. Декларация ж в глобальном масштабе скрыт Дедушка и бабушка :: f, и, в свою очередь Дедушка и бабушка :: f скрыто Родитель :: f. Таким образом, единственным объявлением, которое рассматривается при разрешении перегрузки, является Родитель :: f - и результатом в этом случае является диагностика, потому что сайт вызова предоставляет два аргумента, где Родитель :: f ожидает только одного.
Новых программистов на C ++ часто удивляет, что объявление Родитель :: f доминирует и прячется все деклараций предков, независимо от подписи; то есть, Родитель :: f (int) доминирует и скрывает декларацию Дедушка :: f (двойной, двойной) хотя две функции-члены имеют очень разные сигнатуры.
Также важно отметить, что в C ++ поиск имени предшествует разрешение перегрузки. Если Родитель :: f было несколько перегрузок (например, f (число) и f (двойной, двойной)), компилятор будет выбирать между ними во время разрешения перегрузки; но на этапе поиска имени нас интересует только выбор из трех областей Дедушка и бабушка :: f, Родитель :: f, и :: f. Дело в том, что Дедушка :: f (двойной, двойной) было бы лучше перегрузка чем f (число) не является частью рассмотрения компилятором.
Пример с алмазным наследованием
структура Бабушка и дедушка { пустота ж(int); пустота ж(двойной, двойной);};структура Мать : общественный Бабушка и дедушка { пустота ж(int); // скрывает все перегрузки Mother :: Grandparent :: f};структура Отец : общественный Бабушка и дедушка { };структура Ребенок : общественный Мать, Отец { // Мать :: Бабушка и дедушка - это не тот же подобъект, что и Отец :: Бабушка и дедушка пустота грамм() { ж(2.14, 3.17); } // двусмысленность между Mother :: f и Father :: Grandparent :: f};В приведенном выше примере компилятор вычисляет набор перегрузки для ж который содержит как Мать :: f и Отец :: Дедушка :: f. Компилятор выдает диагностическое сообщение, указывающее, что программа имеет неправильный формат, поскольку имя ж является двусмысленный.
Пример с виртуальным наследованием
структура Бабушка и дедушка { пустота ж(int); пустота ж(двойной, двойной);};структура Мать : общественный виртуальный Бабушка и дедушка { пустота ж(int); // скрывает все перегрузки Mother :: Grandparent :: f};структура Отец : общественный виртуальный Бабушка и дедушка { };структура Ребенок : общественный Мать, Отец { // Mother :: Grandparent - тот же подобъект, что и Father :: Grandparent пустота грамм() { ж(2.14, 3.17); } // разрешается в Mother :: f};В этом последнем примере имя ж еще раз однозначно относится к Мать :: f, потому что Мать :: f скрывает ж заявлено в своем Бабушка и дедушка подобъект. Стандарт называет этот удивительный случай в информативный примечание (§10.2 абзац 10):
Когда виртуальные базовые классы используются, к скрытому объявлению можно добраться по пути через решетку подобъектов, который не проходит через объявление скрытия. Это не двусмысленность.[1]
Даже если Ребенок сам должен был унаследовать практически от Бабушка и дедушка, при поиске имени не будет двусмысленности. Однако если Ребенок должны были унаследовать не-виртуально из Бабушка и дедушка (т.е. struct Child: public Мать, Отец, Бабушка и дедушка), то имя снова будет двусмысленным (между жs заявлено в двух Бабушка и дедушка подобъекты).
Смотрите также
Рекомендации
- ^ а б N3797 Рабочий проект, Стандарт языка программирования C ++. Датировано 13.10.2013.