разрешение перегрузки при использовании базовой функции-члена, введенной в производный класс

Согласно некоторым цитатам из стандарта:
[over.match .функции]/4

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

И рассмотрим следующий код:

#include <iostream>
struct Base {
    void show(double) {
        std::cout << "0" << std::endl;
    }
};
struct Test :Base {
    using Base::show;  //#1
    void show(double) { //#2
        std::cout << "1" << std::endl;
    }
};
int main() {
    Test t;
    t.show(1.2);
}

В соответствии со стандартом, который я привел, это означает, что неявный объектный параметр типа Test принимается как параметр #1.
Для #1 объявление будет show(Test&,double).
Для #2 объявление будет show(Test&,double).
поэтому в целях разрешения перегрузки каждая неявная последовательность преобразования #1 неотличима от последовательности #2, вызов t.show(1.2) будет неоднозначным, однако #2 вызывается, почему? если я что-то упустил в стандарте, поправьте меня.


person xmh0511    schedule 07.04.2020    source источник


Ответы (1)


Test::show(double) имеет ту же подпись, что и Base::show(double); он просто скрывает один из базового класса.

Для с использованием объявления

(выделено мной)

Если в производном классе уже есть член с таким же именем, списком параметров и квалификацией, член производного класса скрывает или переопределяет (не конфликтует с ним) член, введенный из базового класса.

Из стандарта [namespace.udecl]/14

Когда использующий-декларатор переносит объявления из базового класса в производный класс, функции-члены и шаблоны функций-членов в производном классе переопределяют и/или скрывают функции-члены и шаблоны функций-членов с тем же именем, список-типов-параметров ([dcl .fct]), завершающий пункт require-clause (если есть), cv-qualification и ref-qualifier (если есть) в базовом классе (а не конфликтующие). Такие скрытые или переопределенные объявления исключаются из набора объявлений, введенных с помощью объявления-использования. [ Пример:

struct B {
  virtual void f(int);
  virtual void f(char);
  void g(int);
  void h(int);
};

struct D : B {
  using B::f;
  void f(int);      // OK: D​::​f(int) overrides B​::​f(int);

  using B::g;
  void g(char);     // OK

  using B::h;
  void h(int);      // OK: D​::​h(int) hides B​::​h(int)
};

...
person songyuanyao    schedule 07.04.2020