将基类方法引入子类是否有一种不那么直率的方法?

时间:2017-10-03 13:56:34

标签: c++ c++11

考虑

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

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

理想情况下,我希望将仅Base作为参数的fooint作为参数引入Child类,而不是将int类作为参数using Base::foo; 1}}秒。有没有办法可以做到这一点?我的写作foo带来了Base的两种return gmdate($format, $date->getTimestamp());方法。

3 个答案:

答案 0 :(得分:27)

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

现在使用带有Child的两个int重载是不正确的。然而,这不是一个完美的解决方案,因为客户端仍然可以调用Base版本:

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

答案 1 :(得分:10)

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

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

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

答案 2 :(得分:5)

我将列出其他答案中提供的两种解决方案,并详细说明它们之间的区别。

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。当我们将其从重载分辨率中排除时,3,4会选择double,double

手动转发排除 int,int超载被考虑。 =delete没有。

这与using Base::foo(int);的虚构语法最相似(即,仅引入foo的父重载之一)。

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

Live example它的工作原理和where it doesn't