17

我希望有人能够回答为什么以下不起作用。不过请耐心等待,我仍然是个菜鸟……我只是无法弄清楚为什么会出现以下问题

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*。

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

4

5 回答 5

13

What the error is trying to explain is that your assignment "s = t", where s is a std::string, would be valid if t were a std::string too, or if t were a [const] char*. Your conversion operators can convert a t into either, so the compiler has no basis on which to choose one over the other....

You can disambiguate this explicitly by selecting the conversion you want:

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

Or you can provide only one of the conversions and let the user do a further conversion when necessary.

You may find though - in the end - that any conversion operator is more trouble than it's worth... it's telling that std::string itself doesn't provide a conversion operator to const char*.

于 2010-08-19T01:56:52.753 回答
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 *)

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*()

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

这意味着 U1、U2 和 U3 都具有转换等级,并且在第一级中,两者都不比另一个更好。但是,该标准还规定

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

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

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

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

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

那么“如果U1的第二个标准转换序列优于U2的第二个标准转换序列”部分呢?

在 U2 中,第二个标准转换序列需要 const 限定,而在 U3 中则不需要。U3 的第二个标准转换序列是精确匹配。

但正如标准中的表 9 所述,CV 资格也被认为是精确匹配。

因此,就重载解决方案而言,U2 和 U3 也确实无法区分。

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

于 2010-08-19T02:46:19.110 回答
3

There's no exact std::string::operator=. The candidates are, paraphrased,

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

I think things will work if you change it to return const std::string. (EDIT: I'm wrong.) Also note that the first function should return const char *. If you need to cast a string literal to char*, you're doing something wrong; string literals are not writeable.

于 2010-08-19T02:00:59.310 回答
1

Actually, it's because std::string offers an assignment operator that takes a const char*.

于 2010-08-19T01:54:47.587 回答
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= 不能接受浮点数,或者可以吗?还是 float 以某种方式再次等同于 char 的某种变体?

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

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

再次感谢你们的耐心、专业知识和时间——我真的很感激。

于 2010-08-19T05:30:17.040 回答