2012-04-23 74 views
10

编辑:继Mike Seymour的评论之后,我用operator char *() const;替换operator std::string() const;,并相应地更改了实现。这允许隐式转换,但由于某些原因,无符号long int运算符优先于char *运算符,这只是感觉不正确......另外,我不想在c类,当我有std :: string。我有一个预感,我的CustomizedInt类需要从一些东西继承,以支持我期望的功能。有没有人请详细说明Mike对std::basic_string的评论?我不确定我是否理解正确。C++隐式转换运算符优先级


我有这样一段代码:

#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; 
} 

哪个打印 “被叫运营商unsigned long int类型; 123”。我的问题是这些:

  1. 我删除了操作符unsigned long int后,为什么我需要明确地将x转换为std :: string?为什么不直接调用隐式转换运算符(std :: string)?
  2. 是否有任何文档解释哪些隐式转换被允许以及哪些是它们的优先顺序?看来,如果我将运算符unsigned int与运算符unsigned long int一起添加到此类中,则会收到关于运算符<的模糊性的编译器错误...另外,我知道定义这样的运算符可能是可怜的练习,但我不确定我完全理解相关的注意事项。有人可以请他们概述一下吗?仅仅定义公共方法ToUnsignedLongInt和ToString会更好吗?
+0

这是相关的:[通过隐式转换为字符串流式传输对象时的重载分辨率失败](http://stackoverflow.com/questions/6677072/overload-resolution-failure-when-streaming-object-via-implicit-conversion to-str) – 2012-04-23 18:16:51

+0

@Als:让我们慢慢来...我还没有准备好潜入模板:) – 2012-04-23 18:40:46

回答

8

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

<<字符串的版本是一个模板,通过std::basic_string模板的参数parametrised(std::string本身是该模板的专门化)。它只能通过依赖于参数的查找来选择,而且只有当参数实际上是std::basic_string的特化时才有效,而不是可转换的。

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

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

我不知道我完全理解相关的注意事项。有人可以请他们概述一下吗?

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

只是定义公共方法ToUnsignedLongInt和ToString会更好吗?

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

std::cout << std::string(x) << std::endl; 

在C++ 11,你可以宣布他们explicit,所以他们只能以这种方式使用。在我看来,如果可以的话,这将是最好的选择;否则,我会按照你的建议使用显式的转换函数。

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

+0

Mike:感谢您花时间提供这样的详细评论。它确实清楚了一些事情。另外,感谢您发现“void main”这个小问题。我应该记得使用正确的版本,不管是什么:) – 2012-04-23 18:34:05