C++ 派生类中同名但签名不同的函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/411103/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:12:45  来源:igfitidea点击:

Function with same name but different signature in derived class

c++functioninheritancelookupc++-faq

提问by Igor Oks

I have a function with the same name, but with different signature in a base and derived classes. When I am trying to use the base class's function in another class that inherits from the derived, I receive an error. See the following code:

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

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);
    }
};

I receive the following error from the gcc compiler:

我从 gcc 编译器收到以下错误:

In member function `void C::bar()': no matching function for call to `C::foo(std::string&)' candidates are: int B::foo(int)

If I remove int foo(int i){};from class B, or if I rename it from foo1, everything works fine.

如果我int foo(int i){};从 class 中删除B,或者如果我从 重命名它foo1,一切正常。

What's the problem with this?

这有什么问题?

采纳答案by CB Bailey

Functions in derived classes which don't override functions in base classes but which have the same name will hideother 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.

如果您需要调用基本函数,则需要使用A::foo(s). 请注意,这也会同时禁用任何虚拟功能机制A::foo(string)

回答by Johannes Schaub - litb

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 shadowsthe 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:

这是因为如果在您的基地之一中找到名称,名称查找就会停止。它不会超越其他基地。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);
    }
};

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

编辑:标准给出的真实描述是(来自 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.

以下步骤定义了在类作用域 C 中名称查找的结果。首先,考虑了类及其每个基类子对象中名称的每个声明。如果 A 是 B 的基类子对象,则子对象 B 中的成员名称 f 隐藏子对象 A 中的成员名称 f。任何如此隐藏的声明都将不考虑。由 using 声明引入的这些声明中的每一个都被认为来自 C 的每个子对象,这些子对象属于包含 using 声明指定的声明的类型。96) 如果声明的结果集不是所有来自相同类型的子对象,或者集合有一个非静态成员并且包括来自不同子对象的成员,存在歧义并且程序格式错误。否则,该集合是查找的结果。

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).

对于 id 表达式 [类似 "foo" 的东西],名称查找在 this 的类范围内开始;对于限定 id [类似“A::foo”的东西,A 是一个嵌套名称说明符],名称查找从嵌套名称说明符的范围内开始。名称查找发生在访问控制之前(3.4,第 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).

([...] 由我提出)。请注意,这意味着即使您在 B 中的 foo 是私有的,仍然不会找到 A 中的 foo(因为稍后会发生访问控制)。