有没有一种不太直截了当的方法将基类方法引入子类?

Is there a less blunt way of bring base class methods into a child class?

本文关键字:基类 方法 类方法 子类 直截了当 一种 有没有      更新时间:2023-10-16

>考虑

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

理想情况下,我想将仅接受一个int作为参数的Basefoo引入Child类,而不是需要 2ints 的类。有没有办法做到这一点?我的写作using Base::foo;带来了两种fooBase方法。

using 声明将使所有重载可用。你无法阻止这种情况的发生。但是你可以在事后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);

无法将指定的重载函数引入派生类。名称查找规则处理名称,但重载函数具有相同的名称foo

您可以在派生类中编写包装器函数,例如

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

我将列出其他答案中提出的两种解决方案,并详细说明它们的不同之处。

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。 当我们=deleteint,int重载时,它仍然被考虑、选择,我们选择=deleted。 当我们将其从过载分辨率中排除时,3,4会选择double,double

手动转发排除int,int过载。=delete没有。

这最类似于using Base::foo(int);的虚构语法(即,只引入foo的一个父重载)。

请注意,Grandkid只是检测差异的一种简单方法。 重要的是,从过载解决中删除某些内容与=delete重载之间存在差异。

现场示例在哪里有效,在哪里无效。