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

C++ C++;将自定义类型的转换运算符重载为std::string,c++,overloading,operator-keyword,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::

我希望有人能够回答为什么下面的方法不起作用。但请容忍我,我仍然是一个非常愚蠢的人。。。 我就是搞不清楚为什么会发生下面的事情

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;
}
它确实有效

我已经试了几个小时来理解这个错误消息,但最让我困惑的是它对char*有效

我很感激你的任何暗示。 谢谢
Markus

事实上,这是因为
std::string
提供了一个赋值运算符,它接受
const char*

错误试图解释的是,如果
t
也是
std::string
,那么您的赋值“
s=t
”,其中
s
std::string
,将是有效的,或者如果
t
是[
const
]
char*
。您的转换运算符可以将
t
转换为其中任何一个,因此编译器没有选择其中一个的依据

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

s = t.operator std::string();
s = static_cast<std::string>(t);
s=t.operator std::string();
s=静态铸件(t);
或者,您可以只提供其中一个转换,并在必要时让用户进行进一步的转换


不过,最终你可能会发现,任何转换运算符都比它的价值更麻烦。。。它告诉我们,
std::string
本身并没有提供到
const char*

的转换运算符,没有确切的std::string::operator=。这些候选人的意思是

s = (const std::string)(std::string)t;
s = (const char*)t;
s = (char)(int)t;
我认为如果您将其更改为返回const std::string,事情就会成功。(EDIT:我错了。)还要注意,第一个函数应该返回const char*。如果需要将字符串文字强制转换为char*,则说明您做错了什么;字符串文字不可写

$13.3.1.5/2表示“转换 S的函数及其基类 是被考虑的。那些不是 隐藏在S和屈服类型T或a中 可以转换为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表示“a 转换顺序由 考虑到每个 序列中的转换和 任何引用绑定的秩 (13.3.3.1.4).如果其中任何一个 转换秩,序列具有 转换职级;”

这意味着U1、U2和U3都具有转换秩,并且在第一级,它们都不比另一个好。然而,该标准也规定

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

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

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

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

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

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

在U2中,第二个标准转换序列需要常数限定,而在U3中则不需要常数限定。U3的第二个标准转换序列是完全匹配的

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

因此,就过载分辨率而言,U2和U3也确实难以区分


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

好吧,非常感谢大家。我想我已经开始掌握窍门了,有点

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

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

s=t
不知道必须转换为哪种类型,因为有多个潜在的匹配(对于std::string的赋值)转换是用

operator int ()  {return 77;};
operator std::string  () {return "hello";};
(自字符:8bit int)

是这样吗?所以用白痴的话来说,作业的左边没有告诉右边它期望的是哪种类型,所以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;
#包括
#包括
类testClass
{
公众:
运算符浮点(){返回浮点(77.333);};
运算符std::string(){返回“hello”;};
operator int ()  {return 77;};
operator std::string  () {return "hello";};
operator char* () {return (char*)"hi";};
operator std::string  () {return "hello";};
 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;
  }