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

Posted

技术标签:

【中文标题】派生类中具有相同名称但不同签名的函数【英文标题】:Function with same name but different signature in derived class 【发布时间】:2010-09-29 11:50:33 【问题描述】:

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

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 重命名它,一切正常。

这有什么问题?

【问题讨论】:

技术上是 this question 的副本,但这个标题和答案更好。 【参考方案1】:

这是因为如果名称查找在您的其中一个基础中找到名称,则会停止。它不会超越其他基地。 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 中名称查找的结果。首先,为 考虑类及其每个基类子对象中的名称。一个子中的成员名称 f 如果 A 是 B 的基类子对象,则对象 B 在子对象 A 中隐藏成员名称 f。任何声明 如此隐蔽的事物被排除在外。这些声明中的每一个都是由一个 using-declaration 被认为来自 C 的每个子对象,该子对象的类型包含 declara- 由 using-declaration 指定。96) 如果声明的结果集并非全部来自子对象 类型相同,或者集合有一个非静态成员并且包括来自不同子对象的成员,有 模棱两可,程序格式不正确。否则,该集合就是查找的结果。

在另一个地方(就在它上面)有以下说法:

对于一个 id 表达式 [类似 "foo"],名称查找从 this 的类范围开始;对于限定 ID [类似于 "A::foo",A 是一个嵌套名称说明符],名称查找在嵌套名称说明符的范围内开始。名称查找发生在访问控制之前(3.4,第 11 节)。

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

【讨论】:

litb,感谢您的回答。但是当我尝试编译您的代码时,我得到:无法调整对 void A::foo(class basic_string<char,char_traits<char>,allocator<char> >)' in class B' 的访问,因为本地方法 `int B::foo(int)' 具有相同的名称。可能是因为我用的是老版本的gcc 是的,绝对是编译器错误。旧的编译器曾经使用“A::foo;”而不是“使用 A::foo;”但前者在 C++ 中已被弃用。【参考方案2】:

派生类中不覆盖基类中的函数但具有相同名称的函数将隐藏基类中的其他同名函数。

通常认为在派生类中具有与基类中的函数同名的函数是不好的做法,这些函数并不打算覆盖基类函数,因为您所看到的通常不是可取的行为。通常最好给不同的函数起不同的名字。

如果您需要调用基本函数,则需要使用A::foo(s) 来限定调用范围。请注意,这也会同时禁用A::foo(string) 的任何虚函数机制。

【讨论】:

还阅读了 litdb 的回答:您可以通过 B 中的“使用 A::foo”子句“取消隐藏”基本函数。 没错,我只是在寻找可以在呼叫站点使用的解决方案,将基本层次结构视为固定的。 此声明的依据是什么,并遵循以下建议:“通常认为不好的做法在派生类中具有相同名称的函数作为低音类中的函数,它们不打算覆盖基类函数,因为您所看到的通常不是可取的行为。通常最好为不同的函数赋予不同的名称" .如果他们在语义上做同样的事情怎么办?正如 Johannes 的回答所解释的那样,C++ 为您提供了由此引起的问题的解决方案。

以上是关于派生类中具有相同名称但不同签名的函数的主要内容,如果未能解决你的问题,请参考以下文章

C#中具有相同名称和签名但返回类型不同的方法

从派生类调用重载函数

如何在具有相同函数名的派生类中调用基类的函数[重复]

C#防止基类方法被派生类中的new修饰符隐藏

通过“函数参数”中的 const 类型在派生类中具有不同函数参数的虚拟函数会破坏虚拟机制吗? [复制]

C# 关键字--virtual(转)