C++函数重载(了解为什么这种情况不明确)

C++ Function Overloading (Understanding why this case is ambiguous)

本文关键字:情况 不明确 为什么 函数 重载 了解 C++      更新时间:2023-10-16

我头很冷,所以可能是我太拥挤了,无法理解这里发生了什么,但我无法弄清楚以下内容如何不编译?

#include <string>
#include <iostream>
class Base {
public:
virtual void foo(const std::string & data) {
foo(data.data(), data.size());
}
virtual void foo(const void * bytes, int size) = 0;
};
class Derived : public Base{
public:
virtual void foo(const void * bytes, int size) {
std::cout << "Num Bytes: " << size << std::endl;
}
};
int main() {
Derived x;
std::string blah = "Hello";
x.foo(blah);
return 0;
}

我得到的错误是:

./foo.cpp: In function ‘int main()’:
./foo.cpp:25:15: error: no matching function for call to ‘Derived::foo(std::__cxx11::string&)’
x.foo(blah);
^
./foo.cpp:17:18: note: candidate: virtual void Derived::foo(const void*, int)
virtual void foo(const void * bytes, int size) {
^
./foo.cpp:17:18: note:   candidate expects 2 arguments, 1 provided

如果我将foo的第一个实例重命名为fooString,那么一切正常,所以似乎foo的第二个实例以某种方式隐藏了第一个实例。 但是,鉴于第二个实例有两个参数而不是一个参数,我无法弄清楚它是如何模棱两可的。

更新:没有继承也可以正常工作(如果它都是一个类),所以我怀疑我误解了一些继承规则。

类中的virtual void foo(const void * bytes, int size)函数需要两个参数Derived但是当从main调用此函数x.foo(blah);时,您只传递一个参数blah

您需要将两个参数传递给函数调用,因为类中的foo函数Derived期望的那样。

或者,如果要调用Base类的foo函数,请尝试x.Base::foo(blah);

代码的问题在于函数不明确!相反,问题在于Derived中的覆盖实际上隐藏了基类函数!如果要避免这种隐藏,可以使用using-声明使基类版本可用:

class Derived: public Base {
// ...
public:
using Base::foo;
void foo(void const* bytes, int size) override {
// ...
}
};

或者,您可以使用调用站点上的限定来显式调用基类函数:

x.Base::foo(blah);

为了避免派生类在覆盖virtual函数时需要做一些特殊的事情,你最好使用protectedvirtual函数的方法,并让public函数委托给这些函数(这种方法一直用于标准C++库中的virtual函数), 例如:

class Base {
protected:
virtual void do_foo(std::string const& s) {
this->foo(s.c_str(), s.size());
}
virtual void do_foo(void const* bytes, int size) = 0;
public:
void foo(std::string const& s) { this->do_foo(s); }
void foo(void const* bytes, int size) { this->do_foo(bytes, size); }
};

。然后在派生类中适当地重写do_foo()