派生类中具有相同名称但具有不同签名的函数
我有一个具有相同名称的函数,但在基类和派生类中具有不同的签名。 当我试图在inheritance派生的另一个类中使用基类的函数时,我收到一个错误。 看下面的代码:
class A { public: void foo(string s){}; }; class B : public A { public: int foo(int i){}; }; class C : public B { public: void bar() { string s; foo(s); } };
我从gcc编译器收到以下错误:
In member function `void C::bar()': no matching function for call to `C::foo(std::string&)' candidates are: int B::foo(int)
如果我删除int foo(int i){};
从B
类,或者如果我从foo1
重命名,一切工作正常。
这有什么问题?
不重写基类中的函数但具有相同名称的派生类中的函数将在基类中隐藏其他具有相同名称的函数。
通常认为在派生类中具有与低音类中的函数相同的名称的函数是不好的做法,这些函数不打算覆盖基类函数,因为您所看到的通常不是所期望的行为。 通常最好给不同的function不同的名称。
如果您需要调用基本函数,则需要使用A::foo(s)
来调用调用的范围。 请注意,这也会同时禁用A::foo(string)
任何虚函数机制。
这是因为如果名称在您的某个基地中find,名称查找就会停止。 它不会超越其他基地。 B中的函数会隐藏A中的函数。您必须在B的范围内重新声明A的函数,以便在B和C中都可以看到这两个函数:
class A { public: void foo(string s){}; }; class B : public A { public: int foo(int i){}; using A::foo; }; class C : public B { public: void bar() { string s; foo(s); } };
编辑:标准给出的真实描述是(从10.2 / 2):
下面的步骤定义了类范围中的名称查找的结果。首先,考虑在类中和每个基类子对象中的名称的每个声明。 如果A是B的基类子对象,则一个子对象B中的成员名称f在子对象A中隐藏成员名称f。任何隐藏的声明都将被忽略。 使用声明引入的每个声明都被认为是来自C的每个子对象,这些子对象是包含由使用声明指定的声明的types.96)如果结果集声明不是全部来自相同types的子对象,或者该集合具有非静态成员并且包括来自不同子对象的成员,则存在不明确性,并且该程序是不合格的。 否则,该设置是查找的结果。
在另一个地方(正上方)有以下几点说明:
对于一个idexpression式( 类似于“foo” ),名字查找从这个类的范围开始; 对于一个qualified-id( 类似于“A :: foo”,A是一个嵌套名称说明符 ),名称查找从嵌套名称说明符的范围开始。 名称查找发生在访问控制之前(3.4,第11节)。
(由我提出)。 请注意,即使您的B中的foo是私有的,A中的foo仍然不会被find(因为访问控制稍后发生)。