4

考虑下面的类,就像一个简单的例子:

#include <iostream>
#include <string>
using namespace std;

class point {
public:
    int _x{ 0 };
    int _y{ 0 };

    point() {}
    point(int x, int y) : _x{ x }, _y{ y } {}
    operator string() const
        { return '[' + to_string(_x) + ',' + to_string(_y) + ']'; }

    friend ostream& operator<<(ostream& os, const point& p) {

        // Which one? Why?
        os << static_cast<string>(p); // Option 1
        os << p.operator string();    // Option 2

        return os;
    }
};

应该直接调用转换操作员,还是直接调用static_cast并让其完成工作?

这两行几乎会做完全相同的事情(即调用转换运算符),据我所知,它们的行为之间没有真正的区别。所以这里真正的问题是这是否正确。尽管这些对我来说似乎相同,但仍然可能存在细微的差异,人们可能无法理解。

那么除了它们的语法不同之外,这些方法(包括可能不适用于本示例的方法)之间是否存在任何实际差异?应该首选哪一个,为什么?

4

2 回答 2

5

那么这些方法之间是否存在任何实际差异

在这种情况下,据我所知,行为明智。

(包括可能不适用于本例的)

static_cast<X>(instance_of_Y)如果X该类型有一个转换构造函数,也将允许转换Y。对(可能不存在的)转换运算符的显式调用Y无法使用上述转换构造函数。当然,在这种情况下,std::string没有point.

所以,演员阵容更通用,这就是我通常更喜欢的。此外,“将此对象转换为类型string“调用操作员string()更有意义。但是如果出于某种非常奇怪的原因你想避免转换构造函数,那么显式调用转换运算符就可以实现这一点。

于 2016-06-04T11:22:17.897 回答
2

不,您永远不需要直接调用转换运算符成员函数。

如果您在需要std::string对象的地方使用类的实例,则编译器将自动调用转换运算符,如果您使用例如static_cast将实例强制转换为std::string.

简单而愚蠢的例子:

void print_string(std::string const& s)
{
    std::cout << s << '\n';
}

int main()
{
    point p(1, 2);

    print_string(p);  // Will call the conversion operator
    print_string(static_cast<std::string>(p));  // Will call the conversion operator too
}

最接近直接调用函数的方法是使用类似static_cast.


在您的特定情况下,使用输出运算符,您应该使用static_cast. 原因是语义和代码的未来读者和维护者(可能包括您自己)。

它当然可以直接调用转换成员函数(您的选项2),但它会丢失“这里我正在将对象转换为字符串”的语义信息。

如果转换运算符的唯一用途是在输出运算符中使用,您不妨创建一个(私有)函数,将输出流引用作为参数,并直接写入流,并从输出调用该函数操作员。

于 2016-06-04T11:17:48.420 回答