3

我知道这不是关于这个主题的第一个问题,但据我说,我读到的所有其他相关问题(和答案)都有些不合时宜。拿代码

#include <iostream>

using namespace std ;

class Base {
public:
    void methodA() { cout << "Base.methodA()" << endl ;}
};

class Derived : public Base {
public:
    void methodA(int i) { cout << "Derived.methodA(int i)" << endl ;}
};

int  main()
{
  Derived obj;
  obj.methodA();
}

使用最新版本的 g++ 编译此代码会出现错误

no matching function for call to 'Derived::methodA()'

正是因为这个错误,我才找到 Stackoverflow 来寻找答案。但没有一个答案让我信服。这两种方法的签名在区分它们时没有歧义,编译器应该能够在基类中选择方法。只需注释掉

class Derived : public Base {
//public:
//    void methodA(int i) { cout << "Derived.methodA(int i)" << endl ;}
};

并且代码按预期工作。这意味着在基类中隐藏同名成员函数只是成员函数名称,并且不考虑签名,就像函数名称没有被修改一样(在这种情况下,修改应该解决任何歧义)。其他人在类似的问题中写道,这违背了 C++ 的精神(以及我补充说的面向对象),我完全同意他的观点。这是函数重载的一个限制,我真的没有看到任何合理的理由。

显然问题已经关闭,所以我无法在阅读答案后添加回复,除了编辑我自己的初始问题。我相当肯定(但我无法证明这一点)在较旧的 C++ 编译器中,我最初问题中的代码可以毫无问题地编译(然后执行)。我的观点是,我真的看不出这种语言设计(正如回复中所说的那样)选择背后的基本原理。在这种情况下,编译器可以使用所有信息以采取适当的措施,这正是我所期望的。否则看起来,通过语言设计选择,它被选择不考虑成员函数的签名,这听起来很奇怪。我在上面提到的“programmerinterview”阅读了这篇文章,

4

3 回答 3

9

这就是语言的设计方式——内部范围内的名称隐藏外部范围内的名称。这里派生类充当内部作用域,基类充当外部作用域。

如果函数在同一范围内,它们将被视为重载这一事实并不重要。隐藏对名称起作用,而不是对单个函数起作用。

您可以通过将名称显式添加到派生类来覆盖默认值:

class Derived : public Base {
public:
    using Base::methodA;   // Now it is visible!

    void methodA(int i) { cout << "Derived.methodA(int i)" << endl ;}
};
于 2015-10-05T10:41:17.590 回答
2

这意味着在基类中隐藏同名成员函数只是成员函数名,不考虑签名

正确的。这就是语言的设计方式。我也不太喜欢那种语言设计功能。但它有据可查,你别无选择。

于 2015-10-05T10:32:50.827 回答
0

我想你已经明白了。它被称为名称隐藏,这就是语言的制作方式。但是我不认为这是一种不便,因为当您花时间使用 C++ 时,您最终会对这些约定感到非常满意。当您定义与 Base 方法同名的非虚拟方法时,它会在 Derived 类中隐藏 Base 类方法,因此您会收到错误

obj.methodA();

为了避免在派生类中隐藏基类方法,您可以执行以下操作:

obj.Base::methodA();

欲了解更多信息: http: //www.programmerinterview.com/index.php/c-cplusplus/c-name-hiding/

于 2015-10-05T10:40:31.087 回答