【问题标题】:Overriding a Base's Overloaded Function in C++ [duplicate]在 C++ 中重写基的重载函数 [重复]
【发布时间】:2010-10-27 15:46:46
【问题描述】:

可能重复:
C++ overload resolution

我遇到了一个问题,在我的类覆盖其基类的函数后,所有重载版本的函数都被隐藏了。这是设计使然还是我做错了什么?

例如

class foo
{
  public:
    foo(void);
    ~foo(void);
    virtual void a(int);
    virtual void a(double);
};

class bar : public foo 
{
  public:
    bar(void);
    ~bar(void);
    void a(int);
};

下面会给出一个编译错误,说明 bar 中没有 a(double) 函数。

main() 
{
  double i = 0.0;
  bar b;
  b.a(i);
}

【问题讨论】:

  • 如果您发布(如果可能)实际代码会有所帮助。您发布的代码缺少一些细节,例如类定义后的分号和bara 的返回类型...
  • 我无法发布实际代码。我在帖子中添加了详细信息,这并不是真正的语法练习。
  • 我尝试在我的电脑上编译这段代码,没有错误,“ba(i)”在类栏中调用“void a(int)”函数,0.0被转换为0。

标签: c++ inheritance polymorphism overriding


【解决方案1】:

在类栏中,添加

using foo::a;

这是 C++ 中常见的“陷阱”。一旦在类范围内找到名称匹配,它就不会在继承树上进一步查找重载。通过指定 'using' 声明,您将所有 'a' 的重载从 'foo' 带入 'bar' 的范围。然后重载工作正常。

请记住,如果存在使用 'foo' 类的现有代码,则其含义可能会因额外的重载而改变。或者额外的重载可能会引入歧义,并且代码将无法编译。詹姆斯霍普金的回答中指出了这一点。

【讨论】:

  • 完美的解释,非常感谢!
  • 值得牢记詹姆斯霍普金关于在基类中添加附加函数时有效代码更改含义的观点。
  • @Thomas:编辑添加了这一点。谢谢。
【解决方案2】:

这就是语言过去的工作方式。在 using 关键字之前,如果您覆盖了一个重载函数,则必须将它们全部重载:

class bar : public foo 
{
  public:
    bar(void);
    ~bar(void);
    a(int);
    a(double d) { foo::a(d); }  // add this
}

这让语言委员会增加了 using 功能让很多人感到恼火,但一些旧习惯很难改掉;和习惯†有一个很好的论据。

正如 James Hopkins 所指出的,通过添加 using,程序员表示派生类将在没有警告的情况下将任何未来的 foo::a() 覆盖添加到其列表可接受的签名。

这是他描述的一个例子:

#include <iostream>
class Base {
public:
  virtual void f(double){ std::cout << "Base::Double!" << std::endl; }
  // virtual void f(int) { std::cout << "Base::Int!" << std::endl; } // (1)
  virtual ~Base() {}
};

class Derived : public Base {
public:
  // using Base::f; // (2)
  void f(double) { std::cout << "Derived::Double!" << std::endl; }
};

int main(int, char **) {
  Derived d;
  d.f(21);
  return 0;
}

输出将是“Derived::Double!”因为编译器会将整数参数提升为双精度。 g++ 4.0.1 -Wall 不会警告此促销已发生。

取消注释 (1) 以模拟对 Base 添加方法 Base::f(int) 的未来更改。即使使用 -Wall 和“Derived::Double!”,代码也会再次编译,而不会发出警告。仍然是输出。

现在取消注释 (2) 以模拟 Derived 程序员决定包含所有 Base::f 签名。代码编译(没有警告),但输出现在是“Base::Int!”。

†我想不出一个英语单词来形容“那些有习惯的人”和“上瘾的人”太强了。

【讨论】:

  • 这根本不是真的,你可以很好地只覆盖一个函数。
  • 我唯一的辩护是我在 1996 年之前写了很多 C++。叹息。
  • @Thomas Habitué 是个好词——我决定代表英语世界盗用它 ;-)(“奉献者”是我能想到的最接近的词)
  • meriam webster 说:习惯:1) 经常在指定地点的人或 2) 奉献者
  • 教条主义者、墨守成规、不可救药、固执?
【解决方案3】:

这是设计使然。重载解决方案仅限于单个范围。当附加函数被添加到基类或命名空间范围时,它可以防止一些令人讨厌的有效代码更改含义的情况。

【讨论】:

    猜你喜欢
    • 2016-06-22
    • 1970-01-01
    • 2011-12-31
    • 2022-12-22
    • 1970-01-01
    • 2017-02-04
    • 1970-01-01
    相关资源
    最近更新 更多