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

时间:2010-08-19 01:48:40

标签: 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;
}

给了我一个编译时错误:

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>]

如果我不尝试作业

s = t;

它确实有用。

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

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

5 个答案:

答案 0 :(得分:11)

该错误尝试解释的是,如果s = t为{{1},则sstd::string,其中tstd::string。 }},或者如果t是[const] char*。您的转换运算符可以将t转换为任意一个,因此编译器没有依据选择其中一个....

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

s = t.operator std::string();
s = static_cast<std::string>(t);

或者,您只能提供其中一项转化,并允许用户在必要时进行进一步转化。

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

答案 1 :(得分:9)

  

$ 13.3.1.5 / 2州 - “转换   S及其基类的功能   被考虑。那些不是   隐藏在S和收益类型T或a   可以转换为T类型的类型   通过标准转换序列   (13.3.3.1.1)是候选职能。   返回的转换函数   cv限定类型被认为是   产生cv不合格的版本   这个过程的类型   选择候选功能。   返回的转换函数   “引用cv2 X”返回lvalues   输入“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 *)

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

然而,现在必须确定最有效的候选人。涉及的转换序列是:

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

$ 13.3.3.1.1 / 3州 - “a。的等级   转换顺序由确定   考虑每个人的等级   序列中的转换和   任何参考绑定的等级   (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都非常好,并且编译器发现将调用(作为赋值语句的一部分)解析为不明确的,因为没有明确的最佳可行功能

答案 2 :(得分:3)

没有确切的std :: string :: operator =。候选人被转述,

s = (const std::string)(std::string)t;
s = (const char*)t;
s = (char)(int)t;

我认为如果你把它改成const std :: string就行了。编辑:我错了。)另请注意第一个函数应该return const char *。如果你需要将字符串文字强制转换为char *,那么你做错了;字符串文字可写。

答案 3 :(得分:1)

实际上,这是因为std::string提供了一个const char*的赋值运算符。

答案 4 :(得分:0)

好的,非常感谢大家。我想我已经开始了解它,有点......

首先,我不知道这个事实,char只是一个8位的int。谢谢你的澄清。

所以我理解,因为为std :: string定义了三个赋值运算符,每个运算符都有不同的参数(string,char *,const char *),我的表达式的右侧

s=t

不知道,哪个类型必须转换成,因为有多个,可能匹配(对于这个赋值为std :: string)转换用

定义
operator int ()  {return 77;};
operator std::string  () {return "hello";};

(因为char:8bit int)

operator char* () {return (char*)"hi";};
operator std::string  () {return "hello";};

是吗?所以在白痴术语中,赋值的左侧并没有告诉右手边它预期的类型,所以rhs必须从它的选项中进行选择,其中一个与其他选项一样好? std :: string operator =是否容忍我的意图?

到目前为止这么好,我以为我知道了 - 但是,为什么下面的内容也会造成歧义呢?

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

 class testClass
  {
   public:
     operator float ()  {return float(77.333);};
     operator std::string  () {return "hello";};
  };

  int main()
  {
    std::string s = "goodday";
    testClass t;

    s = t;

    cout<< " string: "<<s <<endl;

    return 0;
  }

现在我只定义了一个匹配的转换运算符,对吧? std :: string operator =不能带浮标,还是可以吗?或者浮动在某种程度上等同于某些char变体?

我理解代码为's ='告诉rhs:“给我一个字符串,char *或const char *”

Rhs检查它给出一个testClass实例可以提供什么,唯一的匹配是testClass :: operator std :: string

再次感谢您的耐心,专业知识和时间 - 我真的很感激。