【问题标题】:C++ Implicit Conversion Operators PrecedenceC++ 隐式转换运算符优先级
【发布时间】:2012-05-04 08:50:52
【问题描述】:

编辑:根据 Mike Seymour 的评论,我将 operator std::string () const; 替换为 operator char * () const; 并相应地更改了实现。这允许隐式转换,但由于某种原因,unsigned long int 运算符优先于 char * 运算符,这感觉不太对……另外,我不想在外部暴露像 char * 这样讨厌的 C 东西类,当我有 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;
}

打印“调用运算符 unsigned long int; 123”。我的问题是:

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

【问题讨论】:

标签: c++ casting operator-precedence conversion-operator


【解决方案1】:

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

用于字符串的&lt;&lt; 版本是一个模板,由std::basic_string 模板的参数进行参数化(std::string 本身是该模板的特化)。它只能通过依赖于参数的查找来选择,并且只有当参数实际上是 std::basic_string 的特化时才有效,而不是可以转换为它的东西。

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

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

我不确定我是否完全理解相关的注意事项。有人可以概述一下吗?

我也不完全理解它们;隐式转换、名称查找和模板专业化(可能还有我现在想不到的其他因素)之间的相互作用相当复杂,而且大多数人都没有学习它们的意愿。在很多情况下不会发生隐式转换,而在其他情况下可能会在您不期望的情况下发生;就个人而言,我发现大多数时候避免隐式转换更容易。

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

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

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

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

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

【讨论】:

  • Mike:感谢您抽出宝贵时间提供如此详细的评论。它确实澄清了一些事情。另外,感谢您发现“void main”的小问题。无论如何,我都应该记住使用正确的版本:)
猜你喜欢
  • 2017-07-04
  • 1970-01-01
  • 2014-02-24
  • 2013-02-24
  • 2017-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多