在派生类中具有相同名称但签名不同的函数

我有一个具有相同名称但在基类和派生类中具有不同签名的函数。当我试图在从派生类继承的另一个类中使用基类的函数时,会收到一个错误。请参阅以下代码:

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中重命名它,那么一切都很好。

这有什么问题吗?

48924 次浏览

It is because name lookup stops if it finds a name in one of your bases. It won't look beyond in other bases. The function in B shadows the function in A. You have to re-declare the function of A in the scope of B, so that both functions are visible from within B and 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);
}
};

Edit: The real description the Standard gives is (from 10.2/2):

The following steps define the result of name lookup in a class scope, C. First, every declaration for the name in the class and in each of its base class sub-objects is considered. A member name f in one sub- object B hides a member name f in a sub-object A if A is a base class sub-object of B. Any declarations that are so hidden are eliminated from consideration. Each of these declarations that was introduced by a using-declaration is considered to be from each sub-object of C that is of the type containing the declara- tion designated by the using-declaration.96) If the resulting set of declarations are not all from sub-objects of the same type, or the set has a nonstatic member and includes members from distinct sub-objects, there is an ambiguity and the program is ill-formed. Otherwise that set is the result of the lookup.

It has the following to say in another place (just above it):

For an id-expression [something like "foo"], name lookup begins in the class scope of this; for a qualified-id [something like "A::foo", A is a nested-name-specifier], name lookup begins in the scope of the nested-name-specifier. Name lookup takes place before access control (3.4, clause 11).

([...] put by me). Note that means that even if your foo in B is private, the foo in A will still not be found (because access control happens later).

Functions in derived classes which don't override functions in base classes but which have the same name will hide other functions of the same name in the base class.

It is generally considered bad practice to have have functions in derived classes which have the same name as functions in the bass class which aren't intended to override the base class functions as what you are seeing is not usually desirable behaviour. It is usually preferable to give different functions different names.

If you need to call the base function you will need to scope the call by using A::foo(s). Note that this would also disable any virtual function mechanism for A::foo(string) at the same time.