据我所知,我知道这不是关于这个问题的第一个问题,但我读到的所有其他相关问题(和答案)都略显不合适。 拿代码
#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”中读到了这篇文章,但它没有解释是什么推动了该语言设计的选择(此外,该文章末尾的示例代码中“GrandChildClass”中的“someFunction”没有覆盖,如上所述,同名的上尉类成员函数:两个相同名称的成员函数具有不同的签名 - 因此它不是覆盖的。)
答案 0 :(得分:5)
这就是语言的设计方式 - 内部作用域中的名称隐藏了外部作用域中的名称。这里派生类充当内部范围,基类充当外部范围。
如果函数在同一范围内,那么函数将被视为重载这一事实并不重要。隐藏在名称上,而不是在单个函数上。
您可以通过将名称显式添加到派生类来覆盖默认值:
class Derived : public Base {
public:
using Base::methodA; // Now it is visible!
void methodA(int i) { cout << "Derived.methodA(int i)" << endl ;}
};
答案 1 :(得分:2)
这意味着它只是在基类中隐藏同名会员函数的成员函数名,并且没有考虑签名
正确。这就是语言的设计方式。我也不太喜欢那种语言设计功能。但它有详细记录,你没有选择。
答案 2 :(得分:0)
我想你已经理解了。它被称为名称隐藏,这就是语言的制作方式。但是,当你花时间使用C ++时,我最终会对这些约定感到满意,但我并不认为这是一种不便。当您定义一个与Base方法同名的非虚方法时,它会隐藏Derived类中的Base类方法,因此您将收到
的错误 obj.methodA();
为避免在Derived类中隐藏Base类方法,您可以执行以下操作:
obj.Base::methodA();
了解更多信息:http://www.programmerinterview.com/index.php/c-cplusplus/c-name-hiding/