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


91

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

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,则一切正常。

这是什么问题?


1
从技术上讲,此问题重复一遍,但此标题和答案更好。
Troubadour

Answers:


77

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

通常,在派生类中具有与bass类中的函数同名的函数是不明智的做法,因为您所看到的通常不是期望的行为,所以它们不打算覆盖基类函数。通常最好给不同的函数起不同的名字。

如果需要调用基本函数,则需要使用来确定调用范围A::foo(s)。请注意,这还将同时禁用任何虚拟功能机制A::foo(string)


13
也请阅读litdb的答案:您可以通过在B中使用“ using A :: foo”子句来“取消隐藏”基本函数
。– xtofl

没错,我只是在寻找可以在呼叫站点使用的解决方案,将基本层次结构视为固定的。
CB Bailey

2
该主张的依据是什么,并提出以下建议:“通常认为在衍生类中具有与贝斯类中的函数同名的功能,而无意覆盖基类功能,这是不明智的做法。您所看到的通常不是可取的行为。通常最好为不同的函数赋予不同的名称。如果他们在语义上做同样的事情怎么办?但是,正如Johannes的回答所解释的,C ++为您提供了解决此问题的方法。
Nawaz

107

这是因为如果在您的基地之一中找到名称,名称查找就会停止。它不会超越其他基础。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。如此隐藏的任何声明都将被忽略。使用声明所引入的每个声明均被视为来自C的每个子对象,该子对象的类型包含使用声明所指定的声明。96)如果结果声明集不是全部来自相同类型的子对象,或者该集合具有一个非静态成员并包括来自不同子对象的成员,这会产生歧义,并且程序格式错误。否则,该设置是查找的结果。

在另一个地方(正上方)有以下说法:

对于id表达式[ 类似于“ foo” ],名称查找始于此类的范围;对于合格ID [ 类似于“ A :: foo”,A是嵌套名称说明符 ],名称查找始于嵌套名称说明符的范围。名称查找发生在访问控制之前(3.4,第11节)。

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


小伙子,谢谢你的回答。但是,当我尝试编译您的代码时,我得到:void A::foo(class basic_string<char,char_traits<char>,allocator<char> >)' in 由于本地方法`int B :: foo(int)'具有相同的名称,因此无法调整对类B'的访问。也许是因为我使用了旧版的gcc
Igor Oks 2009年

1
是的,绝对是编译器错误。以前使用“ A :: foo;”的旧编译器 而不是“使用A :: foo;” 但是前者在C ++中已弃用。
Johannes Schaub-litb
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.