C++将自定义类型的转换运算符重载为std :: string

Mar*_*kus 14 c++ overloading operator-keyword

我希望有人能够回答为什么以下不起作用.虽然忍受我,我仍然是一个菜鸟......我只是无法深究为什么以下

using namespace std;
#include <string>
#include <iostream>

class testClass
{
public:
 operator char* () {return (char*)"hi";};
 operator int ()  {return 77;};
 operator std::string  () {return "hello";};
};

int main()
{
 char* c;
 int i;
 std::string s = "goodday";

 testClass t;

 c = t;
 i = t;
 s = t;

 cout<< "char: " << c << " int: " << i << " string: "<<s<<endl;

 return 0;
}
Run Code Online (Sandbox Code Playgroud)

给我一个编译时错误:

myMain.cpp: In function ‘int main()’:
myMain.cpp:23: error: ambiguous overload for ‘operator=’ in ‘s = t’
/usr/include/c++/4.2.1/bits/basic_string.h:500: note: candidates are: std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]
/usr/include/c++/4.2.1/bits/basic_string.h:508: note:                 std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(const _CharT*) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]
/usr/include/c++/4.2.1/bits/basic_string.h:519: note:                 std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(_CharT) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]
Run Code Online (Sandbox Code Playgroud)

如果我不尝试任务

s = t;
Run Code Online (Sandbox Code Playgroud)

它确实有效.

我已经尝试了几个小时甚至理解错误信息,但最令我困惑的是,它对char*有效.

我很感激任何提示.谢谢!马库斯

Ton*_*roy 11

哪些错误是试图说明的是,你的任务" s = t",其中s是一个std::string如果,将是有效的t是一个std::string太,或者t是一个[ const] char*.您的转换运算符可以将a转换t为任意一个,因此编译器没有依据选择其中一个....

您可以通过选择所需的转换来明确消除歧义:

s = t.operator std::string();
s = static_cast<std::string>(t);
Run Code Online (Sandbox Code Playgroud)

或者,您只能提供其中一个转化,并在必要时让用户进行进一步转换.

你可能会发现 - 最终 - 任何转换运算符都比它的价值更麻烦...它告诉它std::string本身不提供转换运算符const char*.


Chu*_*dad 9

$ 13.3.1.5/2状态 - "S及其基类的转换函数被考虑.那些不隐藏在S中并且产生类型T的类型或者可以通过标准转换序列转换为类型T的类型(13.3.3.1) .1)是候选函数.返回cv限定类型的转换函数被认为在这个选择候选函数的过程中产生该类型的cv非限定版本.返回"引用cv2 X"的转换函数返回类型的左值因此,"cv2 X"被认为是在选择候选函数的过程中产生X."

赋值s = t的工作原理如下:

a)所有类型为't'(testClass)的成员都被认为可以将't'转换为's'.

Candidate 1: operator string();   // s created using member string::operator=(string const&)
Candidate 2: operator char *()    // s created using member string::operator=(char const*)
Candidate 3: operator char *()    // s created using member string::operator=(char *)
Run Code Online (Sandbox Code Playgroud)

b)以上所有候选者都是可行的(即,在没有其他候选者的情况下,编译器可以成功解析对其中任何一个的函数调用)

c)但是,现在必须确定最有可行的候选人.涉及的转换序列是:

Candidate 1: U1 : operator string()
Candidate 2: U2 : operator char*()->const qualification to match string::operator=(char const*)
Candidate 3: U3 : operator char*()
Run Code Online (Sandbox Code Playgroud)

$ 13.3.3.1.1/3状态 - "转换序列的等级是通过考虑序列中每个转换的等级和任何参考绑定的等级(13.3.3.1.4)来确定的.如果其中任何一个具有转换等级,序列具有转换等级;"

这意味着U1,U2和U3都具有转换等级并且在第一级别上都不比另一级好.但是,该标准还指出

用户定义的转换序列U1是比另一个用户定义的转换序列U2更好的转换序列,如果它们包含相同的用户定义的转换函数或构造函数,并且如果U1的第二标准转换序列优于U2的第二标准转换序列.

那么,让我们看看这意味着什么.

在U1和U2之间,它们涉及不同的转换函数,因此没有一个比另一个好

在U1和U3之间,它们涉及不同的转换函数,因此没有一个比另一个好

那么U1和U2呢?它们涉及相同的转换函数,它满足上述"和"条件的第一部分

那么"和U1的第二个标准转换序列是否优于U2的第二个标准转换序列"的部分呢.

在U2中,第二个标准转换序列需要const限定,其中在U3中这不是必需的.U3的第二个标准转换序列是精确匹配.

但正如标准中的表9所示,CV资格也被认为是完全匹配.

因此,就重载分辨率而言,U2和U3也是无法区分的.

这意味着U1,U2和U3都非常好,并且编译器发现将调用(作为赋值语句的一部分)解析为不明确的,因为没有明确的最佳可行函数


Ste*_*dit 1

实际上,这是因为std::string提供了一个接受const char*.