C++隐式转换运算符优先级

Mih*_*dor 10 c++ casting operator-precedence conversion-operator

编辑:继迈克·西摩的评论,我换成operator std::string () const;operator char * () const;,并相应地改变了实现.这允许隐式转换,但是,由于某种原因,unsigned long int运算符优先于char*运算符,这只是感觉不对...而且,我不想暴露讨厌的C之类的东西,比如char*class,当我有std :: string时.我有一种预感,我的CustomizedInt类需要继承一些东西才能支持我想要的功能.有人可以详细说明迈克的评论std::basic_string吗?我不确定我是否理解得当.


我有这段代码:

#include <string>
#include <sstream>
#include <iostream>

class CustomizedInt
{
private:
    int data;
public:
    CustomizedInt() : data(123)
    {
    }
    operator unsigned long int () const;
    operator std::string () const;
};

CustomizedInt::operator unsigned long int () const
{
    std::cout << "Called operator unsigned long int; ";
    unsigned long int output;
    output = (unsigned long int)data;
    return output;
}

CustomizedInt::operator std::string () const
{
    std::cout << "Called operator std::string; ";
    std::stringstream ss;
    ss << this->data;
    return ss.str();
}

int main()
{
    CustomizedInt x;
    std::cout << x << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

其中打印"Called operator unsigned long int; 123".我的问题是这些:

  1. 删除运算符unsigned long int后,为什么需要显式地将x转换为std :: string?为什么不直接调用隐式强制转换操作符(std :: string)?
  2. 是否有任何文档可以解释允许哪些隐式强制转换以及哪些是优先顺序?看来如果我将运算符unsigned int与运算符unsigned long int一起添加到此类中,我会收到有关<<运算符的歧义的编译器错误...
  3. 此外,我知道定义这样的运算符可能是不好的做法,但我不确定我是否完全理解相关的警告.有人可以概述一下吗?将公共方法ToUnsignedLongInt和ToString定义为更好的做法吗?

Mik*_*our 8

删除运算符unsigned long int后,为什么需要显式地将x转换为std :: string?为什么不直接调用隐式强制转换操作符(std :: string)?

<<for strings 的版本是一个模板,由模板的参数std::basic_string(std::string本身是该模板的特化)进行参数化.它只能通过依赖于参数的查找来选择,并且仅在参数实际上是特化时才有效std::basic_string,而不是可转换为特殊的.

是否有任何文档可以解释允许哪些隐式强制转换以及哪些是优先顺序?

规则非常复杂,您需要阅读完整故事的C++标准.简单的经验法则是隐式转换不能包含多个用户定义的转换,并且(如您所知)隐式转换的结果不能用于通过依赖于参数的查找来选择模板特化.

我不确定我是否完全理解相关的警告.有人可以概述一下吗?

我也不完全理解他们; 隐式转换,名称查找和模板特化(以及可能是我现在无法想到的其他因素)之间的相互作用相当复杂,而且大多数人并不倾向于全部学习它们.有很多情况下隐式转换不会发生,而其他情况可能会发生在您不期望的情况下; 就个人而言,我发现在大多数情况下避免隐式转换更容易.

将公共方法ToUnsignedLongInt和ToString定义为更好的做法吗?

这可能是一个好主意,以避免不必要的转换.您可以通过保留问题来解决问题,并在必要时明确使用它们:

std::cout << std::string(x) << std::endl;
Run Code Online (Sandbox Code Playgroud)

在C++ 11中,您可以声明它们explicit,以便它们只能以这种方式使用.在我看来,如果可以,这将是最好的选择; 否则,我会按照你的建议使用显式转换函数.

顺便说一句,返回类型main()必须是int,而不是void.