Подтвердить что ты не робот

Существует ли менее тупой способ привести методы базового класса в дочерний класс?

Рассмотрим

struct Base
{
    int foo(int);
    int foo(int, int);
};

struct Child : Base
{
    using Base::foo;
    int foo(int, int, int);
};

В идеале я хочу привести класс Base foo, который принимает только один int в качестве параметра в класс Child, а не тот, который принимает 2 int s. Есть ли способ, которым я могу это сделать? В моем письме using Base::foo; приведены методы foo Base.

4b9b3361

Ответ 1

Использование декларации сделает доступными все перегрузки. Вы не можете предотвратить это. Но вы можете delete перегрузки, которые вы не хотите, после того, как:

struct Base
{
    int foo(int);
    int foo(int, int);
};

struct Child : Base
{
    using Base::foo;
    int foo(int, int) = delete;
    int foo(int, int, int);
};

Теперь использование двух перегрузок int с Child плохо сформировано. Однако это не идеальное решение, так как клиент все еще может вызвать базовую версию:

Child c;
c.Base::foo(0, 0);

Ответ 2

Невозможно привести указанную перегруженную функцию в производный класс. Правило поиска имен относится к именам, но перегруженные функции имеют одно и то же имя foo.

Вы можете написать функцию-оболочку в производном классе, например.

struct Child : Base
{
    int foo(int x) { return Base::foo(x); }
    int foo(int, int, int);
};

Ответ 3

Я собираюсь перечислить оба решения, представленные в других ответах, и подробно расскажу, как они отличаются.

struct Child : Base
{
  int foo(int x) { return Base::foo(x); }
  int foo(int, int, int) {  std::cout << 3; return 33; }
};

это делает именно то, что вы хотите, но вы должны повторить подпись.

Несколько другой результат:

struct Child : Base
{
  using Base::foo;
  int foo(int,int)=delete;
  int foo(int, int, int) { std::cout << 3; return 314; }
};

Чтобы понять, как это происходит, представьте, что мы сделали это:

struct Grandkid : Child
{
  using Child::foo;
  int foo(double, double) { std::cout << 2; return 42; }
};

и мы сделали:

Grandkid x;
x.foo(3,4);

В случае с =delete это приведет к ошибке компилятора.

3,4 предпочитает int,int над double,double. Когда мы =delete перегружаем int,int, он по-прежнему считается выбранным и выбираем =delete d one. Когда мы вместо этого исключаем его из разрешения перегрузки, 3,4 выбирает double,double.

Ручная пересылка исключает перегрузку int,int. =delete нет.

Это больше похоже на мнимый синтаксис using Base::foo(int); (т.е. только приведение одной из родительских перегрузок foo).

Обратите внимание, что Grandkid - это всего лишь один простой способ определить разницу. Важно то, что есть разница между удалением чего-либо из разрешения перегрузки и =delete перегрузки.

Пример в реальном времени, где он работает, и где он не " т.