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

C++ 派生类中名称相同但签名不同的函数,c++,function,inheritance,lookup,c++-faq,C++,Function,Inheritance,Lookup,C++ Faq,我有一个同名的函数,但在基类和派生类中有不同的签名。当我试图在从派生类继承的另一个类中使用基类的函数时,我收到一个错误。请参阅以下代码: 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

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

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 fooint I{};从B类,或者如果我从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中名称查找的结果 将考虑类及其每个基类子对象中的名称。一个子系统中的成员名称f- 如果a是B的基类子对象,则对象B在子对象a中隐藏成员名称f。任何声明 那些如此隐蔽的东西被排除在考虑之外。由 使用声明被认为来自C的每个子对象,该子对象属于包含声明的类型- 如果生成的声明集并非全部来自子对象,则由using-declaration.96指定 相同类型,或集合具有非静态成员且包含来自不同子对象的成员,则存在 模棱两可,程序格式不正确。否则,该集合就是查找的结果

在它上面的另一个地方,它说:

对于id表达式[foo]而言,名称查找从该表达式的类范围开始;对于限定id[类似于a::foo,a是嵌套名称说明符],名称查找从嵌套名称说明符的范围开始。名称查找发生在访问控制3.4第11条之前


[…]由我提出。请注意,这意味着即使B中的foo是私有的,A中的foo仍然找不到,因为访问控制会在以后进行。

派生类中的函数如果不重写基类中的函数,但具有相同名称,则会在基类中隐藏其他同名函数

通常认为,在派生类中具有与bass类中的函数同名的函数是不好的做法,因为您看到的通常不是理想的行为,因此这些派生类中的函数不打算重写基类函数。通常最好为不同的函数指定不同的名称


如果需要调用基函数,则需要使用::foos来确定调用的范围。请注意,这也将同时禁用::foostring的任何虚拟函数机制。

litb,谢谢您的回答。但当我试图编译代码时,我得到:无法调整访问权限以使B类中的A::fooclass basic_字符串无效,因为具有相同名称的本地方法`int B::fooint'。可能是因为我使用了一个旧版本的gccyeah,这肯定是一个编译器错误。以前的编译器使用A::foo;而不是使用::foo;但是前者在C++中被弃用。也读LITDB的答案:你可以用“A::FoO”子句在B.Trtrue中“取消”隐藏基函数,我只是在寻找一个可以在调用站点使用的解决方案,将基类层次结构视为固定的。这一主张的依据是什么,然后是建议:在派生类中使用与bass类中的函数同名的函数通常被认为是一种不好的做法,因为您通常不希望看到这些函数覆盖基类函数行为通常最好为不同的函数指定不同的名称。如果他们在语义上做相同的事情呢?C++提供了一个解决这个问题的方法,尽管Johannes的回答是这样的。技术上是一个副本,但是这个标题有更好的答案。