类变量会在显式转换时隐式转换为整型,尽管已经有了显式转换。

3

在foo类中,我编写了将隐式转换运算符转换为double和将显式转换运算符转换为int的函数,并编写了一个以int作为参数的函数。尽管使用未转换的foo对象调用该函数,但代码仍会执行。

我使用了gcc PRETTY_FUNCTION并发现foo对象被转换为double,然后再转换为int。

class foo
{
public:
    int x, y;
    foo(int x, int y) : x{x}, y{y} {}
    explicit operator int() {cout << __PRETTY_FUNCTION__ << "\n"; return x/y;}
    operator double() {cout << __PRETTY_FUNCTION__ << "\n"; return double(x)/double(y);}
};

void printint(int x)
{
    cout << x << "\n";
}

int main()
{
    foo var(1,2);
    printint(var);
}

我原以为这段代码不能编译通过,因为它有一个显式转换运算符,但事实上它可以编译通过并输出0作为int(1/2)的值。
程序的输出结果如下: foo::operator double() 0

那么,如果类对象可以被隐式地转换为某些东西,然后再转换为int,那么显式运算符有什么用呢?它不应该防止这种情况发生吗? - doromaanim
2个回答

10

cppreference上得知,隐式类型转换序列包括以下步骤:

1) 零个或一个标准转换序列;

2) 零个或一个用户自定义的转换;

3) 零个或一个标准转换序列。

因此你的foo可以转换为double(第二步),然后double再转换为int(第三步)。

如果你想使代码无法编译,你还需要将double转换设置为explicit。使用explicit只能防止在第二步中将foo转换为int,但整个序列中仍然可以通过隐式转换实现转换。由于步骤(1)和(3),隐式转换可能会产生意外的副作用,需要特别注意。


0

当然它会使用 double 转换运算符,然后将 double 强制转换为 int。可以隐式调用 double 转换运算符。去掉 explicit 就不会先强制转换为 double

它不能使用 explicit operator int(),因为有 explicit


显式转换运算符的目的不就是防止对象被强制转换为 int,除非在代码中声明了吗? - doromaanim
1
如果这是唯一可能的对话,那么是的。但是,由于您的类可以隐式转换为“double”,而“double”可以隐式转换为“int”,因此编译器选择执行该操作。您的“explicit”对第二个转换没有影响,因为它不涉及您的类。 - Remy Lebeau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接