static_cast 还是直接调用转换运算符?

static_cast vs. direct call to conversion operator?

考虑以下 class,作为一个简单的例子:

#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 然后让它完成工作?

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

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

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

如果您使用 class 的实例,其中需要 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),但它会丢失表示 "here I'm converting the object to a string".

的语义信息

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

So are there any practical differences between those approaches

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

(including ones that might not apply to this example)

如果 X 具有类型 Y 的转换构造函数,

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

的转换构造函数

因此,演员表更通用,这也是我总体上更喜欢的。另外 "convert this object to type string""call the operator string()" 更有意义。但是如果出于某种非常奇怪的原因你想避免转换构造函数,那么显式调用转换运算符就可以实现这一点。