我希望有人能够回答为什么以下不起作用。虽然忍受我,但我仍然非常喜欢... 我只是无法深究以下为什么
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 *有效。
我很感激任何提示。 谢谢! 马库斯
答案 0 :(得分:11)
该错误尝试解释的是,如果s = t
为{{1},则s
为std::string
,其中t
为std::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
再次感谢您的耐心,专业知识和时间 - 我真的很感激。