Существует ли менее тупой способ привести методы базового класса в дочерний класс?
Рассмотрим
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
.
Ответы
Ответ 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
перегрузки.
Пример в реальном времени, где он работает, и где он не " т.