1

我目前正在使用 C/C++ 进行一些套接字编程。为了能够使用更简洁的接口和更面向对象的结构,我决定围绕 C 套接字 API 的部分编写一些简单的包装类,但在这样做时我偶然发现了一个问题:

给定以下代码:

// Global method
int foo(int x)
{
    return x;
}

// Class that calls the global method
class FooBar
{
public:
    void foo() { return; };
    void baz() { foo(1); }
};

g++ 给出以下错误消息:

test.cpp: In member function ‘void FooBar::baz()’:
test.cpp:10: error: no matching function for call to ‘FooBar::foo(int)’
test.cpp:9: note: candidates are: void FooBar::foo()

重命名类方法解决了这个问题。

为什么即使方法签名不同,也会存在某种命名冲突?解决此问题的最佳方法是什么?

谢谢/埃里克

4

3 回答 3

8

问题是它首先查看你的类的范围,然后找到一个 foo 函数。然后查找将停止,编译器会尝试匹配参数。由于它在您的类的该范围内只有一个 foo 函数,因此调用该函数会失败。

您需要明确声明要调用 free 函数:

::foo(1);

另一种解决方案是在 baz 中声明函数:

void baz() { int foo(int); foo(1); }

假定定义 foo 函数的范围是类的周围命名空间。

于 2008-11-26T13:01:08.120 回答
3

您必须使用范围解析尝试:

::foo(1);

于 2008-11-26T13:00:35.687 回答
2

解决方案是:

void baz() { ::foo(1); }

“为什么即使方法签名不同,也会有某种命名冲突?”

因为 C++ 总是首先查找名称。当它在相关范围内找到一个名称时,它会检查该范围内该名称可用的签名。因此,foo()成员函数将自由函数隐藏在foo(int)其范围内的任何位置(即,在类的其他成员函数中)。

出于同样的原因,以下代码将无法编译:

struct A {
    virtual void foo(int) = 0;
    // attempt to provide a useful helper
    virtual void foo() { foo(23); }
};

struct B : public A {
    void foo(int i) {
        std::cout << i << "\n";
    }
};

int main() {
    B b;
    b.foo(); // oops, can't find foo(), because class B hid it
    A &a = b;
    a.foo(); // that works. So much for Liskov's substitution principle.
}

正如所写的那样,B 已损坏,因为它从其基类中删除了功能(尽管仅在称为 B 时,而不是在称为 A 时)。litb 在下面的评论中提供了一个链接,解释了如何解开它。

于 2008-11-26T13:01:51.363 回答