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

发布于 2024-07-11 18:04:24 字数 603 浏览 7 评论 0原文

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

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

这有什么问题吗?

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:

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.

What's the problem with this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凉宸 2024-07-18 18:04:24

这是因为如果在您的基地之一找到名称,名称查找就会停止。 它不会把目光投向其他基地。 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 的每个子对象,该子对象的类型包含声明-
由 using-declaration 指定。96) 如果声明的结果集并非全部来自子对象
具有相同类型,或者集合具有非静态成员并包含来自不同子对象的成员,则有
含糊不清,程序格式不正确。 否则该集合就是查找的结果。

它在另一个地方(就在它的上方)有以下内容:

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

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

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

一抹微笑 2024-07-18 18:04:24

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

通常认为派生类中的函数与低音类中的函数同名是不好的做法,而派生类中的函数并不打算覆盖基类函数,因为您所看到的通常不是理想的行为。 通常最好为不同的函数指定不同的名称。

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文