基类中抽象方法的包装器实现

时间:2015-07-17 02:50:30

标签: c++ inheritance abstract-class

我有一个继承了许多子类的基类。我需要为抽象方法定义一个新签名,它主要是一个包装器。我试过这个

class B {
 public:
  virtual void f() = 0;
  void f(string msg) { /* print msg and call f() */ }
};

class D : public B {
 public:
  void f() override { /* implementatation */}
};

int main() {
  D d;
  d.f("msg");
}

但是它没有编译并给出以下错误

error: no matching function for call to 'D::f(string)

我的问题是:

  1. 为什么D::f(string)无法解决?
  2. 为什么以下任何一项解决了这个问题?
    • f(string)重命名为f2(string)(丑陋)
    • 定义D::f(string x) { B::f(x)}(丑陋,因为它必须在每个子类中定义)
    • 删除抽象方法B::f()(不可接受)
  3. 有更好的解决方案吗?

2 个答案:

答案 0 :(得分:5)

问题是你隐藏 B::f(std::string)

class D : public B {
public:
  void f() override;
};

当您致电D.f("msg")时,名称查询会在f()中找到一个D并停止查找。我们首先找到候选函数然后执行重载决策。由于那个碰巧没有参数,你得到编译错误。

如果您想使用f的其他重叠,您还需要将其带入D,如下所示:

class D : public B {
public:
  using B::f;
  void f() override;
};

现在我们有D::f()(重写的虚函数)和D::f(std::string )(我们从B引入)。

另一个简单的解决方案是简单地重命名一个或另一个函数,这样你就不会有这个问题。

答案 1 :(得分:1)

您使用的是NVI个身份证吗?如:

class B {
 public:
  virtual void f() = 0;
  void f(string msg) { 
    /* print msg and call f() */
    std::cout << msg;
    f();
  }
  virtual ~B() {}
};

然后你应该尽可能尝试从基类(通过引用或指针)调用非虚拟成员函数,例如:

D d;
B& b = d;
b.f("msg");