我有一个同名的函数,但在基类和派生类中有不同的签名。当我尝试在从派生继承的另一个类中使用基类的函数时,我收到一个错误。请参阅以下代码:
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)
如果我从类 B
中删除 int foo(int i){};
,或者如果我从 foo1
重命名它,一切正常。
这有什么问题?
这是因为如果在您的一个基地中找到名称,名称查找就会停止。它不会超越其他基地。 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 开始):
以下步骤定义在类范围 C 中名称查找的结果。首先,考虑类中及其每个基类子对象中名称的每个声明。如果 A 是 B 的基类子对象,则一个子对象 B 中的成员名称 f 隐藏子对象 A 中的成员名称 f。任何如此隐藏的声明都将不予考虑。由 using 声明引入的这些声明中的每一个都被认为来自 C 的每个子对象,这些子对象的类型包含由 using 声明指定的声明。96) 如果声明的结果集不是全部来自相同类型的子对象,或者该集合具有非静态成员并包含来自不同子对象的成员,则存在歧义并且程序格式错误。否则,该集合是查找的结果。
它在另一个地方(就在它上面)有以下说法:
对于 id-expression [类似于 "foo"],名称查找从 this 的类范围开始;对于限定 ID [类似于“A::foo”,A 是嵌套名称说明符],名称查找在嵌套名称说明符的范围内开始。名称查找发生在访问控制之前(3.4,第 11 节)。
([...] 由我提出)。请注意,这意味着即使您在 B 中的 foo 是私有的,仍然无法找到 A 中的 foo(因为稍后会发生访问控制)。
派生类中的函数不覆盖基类中的函数但具有相同名称的函数将隐藏基类中的其他同名函数。
通常认为在派生类中具有与低音类中的函数同名的函数被认为是不好的做法,这些函数并不打算覆盖基类函数,因为您所看到的通常不是可取的行为。通常最好给不同的函数起不同的名字。
如果您需要调用基本函数,则需要使用 A::foo(s)
来限定调用范围。请注意,这也会同时禁用 A::foo(string)
的任何虚拟功能机制。
void A::foo(class basic_string<char,char_traits<char>,allocator<char> >)' in
class B' 的访问,因为本地方法 `int B::foo(int)' 具有相同的名称。也许是因为我使用的是旧版本的 gcc