C++加法过载模糊

Nat*_*ate 2 c++ gcc operator-overloading stdstring

我在我的代码库中遇到了一个棘手的难题.我不知道为什么我的代码会生成此错误,但(例如)std :: string则不然.

class String {
public:
    String(const char*str);
    friend String operator+ ( const String& lval, const char *rval );
    friend String operator+ ( const char *lval, const String& rval );
    String operator+ ( const String& rval );
};
Run Code Online (Sandbox Code Playgroud)

这些的实现很容易想象你自己.

我的驱动程序包含以下内容:

String result, lval("left side "), rval("of string");
char lv[] = "right side ", rv[] = "of string";
result = lv + rval;
printf(result);
result = (lval + rv);
printf(result);
Run Code Online (Sandbox Code Playgroud)

这在gcc 4.1.2中生成以下错误:

driver.cpp:25: error: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second:
String.h:22: note: candidate 1: String operator+(const String&, const char*)
String.h:24: note: candidate 2: String String::operator+(const String&)
Run Code Online (Sandbox Code Playgroud)

到目前为止一切都那么好吧?遗憾的是,我的String(const char*str)构造函数非常方便使用隐式构造函数,使用explicit关键字来解决这个问题只会导致一堆不同的问题.

而且...... std :: string不必诉诸于此,我无法弄清楚为什么.例如,在basic_string.h中,它们声明如下:

template<typename _CharT, typename _Traits, typename _Alloc>
basic_string<_CharT, _Traits, _Alloc>
operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
          const basic_string<_CharT, _Traits, _Alloc>& __rhs)

template<typename _CharT, typename _Traits, typename _Alloc>
basic_string<_CharT,_Traits,_Alloc>
operator+(const _CharT* __lhs,
          const basic_string<_CharT,_Traits,_Alloc>& __rhs);
Run Code Online (Sandbox Code Playgroud)

等等.basic_string构造函数未声明为显式.这怎么不会导致我得到同样的错误,我怎样才能实现相同的行为?

Jam*_*lis 9

模糊性的原因是,只有当一个候选函数的参数都不比另一个参数更差时,它才优于另一个候选函数.考虑你的两个功能:

friend String operator+(const String&, const char*); // (a)
String operator+(const String&);                     // (b)
Run Code Online (Sandbox Code Playgroud)

你打电话operator+给a String和a const char*.

类型的第二个参数const char*明显与(a)比(b)更好地匹配.它与(a)完全匹配,但(b)需要用户定义的转换.

因此,为了存在歧义,第一个参数必须比(a)更好地匹配(b).

String在电话会议中的左侧operator+是不是常量.因此,它匹配(b),这是一个非const成员函数,优于(a),它取a const String&.

因此,以下任何解决方案都将消除歧义:

  • 将成员更改operator+为const成员函数
  • 将非成员更改operator+String&取代而不是const String&
  • operator+在左侧调用const String

显然,第一个,也是UncleBens建议的,是最好的方式.


Jam*_*lis 5

在这种情况下,只需定义operator+:

String operator+(const String& lval, const String& rval);
Run Code Online (Sandbox Code Playgroud)

因为你提供了一个构造函数char*,a String可以char*在调用期间构造一个operator+.例如:

String hello = "Hello, ";
const char* world = "world!";

String helloWorld = hello + world;
Run Code Online (Sandbox Code Playgroud)

String将使用char* world(因为您的构造函数不明确)的内容构造临时,然后将两个String对象传递给operator+.