如何解释显式转换运算符

How to interpret the explicit cast operator

因为我们可以调用显式转换运算符,使用 static_cast、C 风格转换或构造函数风格转换。我很困惑操作员如何准确地解释这三个演员表。

例如,考虑以下代码。 display_balance() 中的 const Money& balance 可以通过三种方式转换为 double。那么这些 cast 解释的是什么。我认为 Money 中只有一个显式转换运算符,因此调用可能是 balance.operator ()。实在想不通这三个不同的casting是怎么解释的

class Money
{
public:
    Money() : amount{ 0.0 } {};
    Money(double _amount) : amount{ _amount } {};
    explicit operator double() const { return amount; }
private:
    double amount;
};

void display_balance(const Money& balance)
{
    std::cout << "The balance is: " << (double)balance << "\n";
    std::cout << "The balance is: " << double(balance) << "\n";
    std::cout << "The balance is: " << static_cast<double>(balance) << "\n";
}

类型转换

决定如何执行转换的不是转换时使用的语法,而是基于变量类型的上下文。

当编译器发现您正在尝试从 Money 转换为 double 时,它会尝试找出一种方法来完成此操作 - 在每种情况下,它都会使用 Money::operator double() 运算符,因为在每种情况下都将 double 指定为目标类型。

C++ 由于历史原因,几乎总是允许你以多种不同的方式完成一项任务;甚至它的名字都暗示了它最初的目标:extending the C language.

考虑以下语法:

Money balance(100.0);

// C-Style Cast
(double)balance;              //< double with value 100.0

// Functional Cast
double(balance);              //< double with value 100.0
double{ balance };            //< double with value 100.0

// Static Cast
static_cast<double>(balance); //< double with value 100.0

编译后,您使用的语法实际上没有任何区别;他们都打电话给 Money::operator double().

当然,选角总是受制于operator precedence

注意:虽然在这种情况下所有方法都是相同的,但并非在所有情况下都是如此。
尽可能使用 static_cast 而不是 c-style 或函数式转换 - 您可以阅读更多关于 here.

的原因

显式与隐式类型转换

考虑以下对象:

  • Money 是你的 class.
  • CashMoney 的副本,允许隐式转换。
class Money
{
public:
    Money() : amount{ 0.0 } {};
    Money(double _amount) : amount{ _amount } {};

    // This is an explicit casting operator:
    explicit operator double() const { return amount; }
private:
    double amount;
};

class Cash
{
public:
    Cash() : amount{ 0.0 } {};
    Cash(double _amount) : amount{ _amount } {};

    // This is an implicit casting operator
    operator double() const { return amount; }
private:
    double amount;
};

现在考虑以下接受 double 的函数:

void BuySomething(double amount) {}

为了BuySomething()Money,我们必须首先明确地将它转换为double

Money money(500.0);

BuySomething(static_cast<double>(money));
BuySomething((double)money);
BuySomething(double(money));
BuySomething(double{ money });

// We can also just call the operator directly:
BuySomething(money.operator double());

但是,我们可以 BuySomething()Cash 而无需首先显式转换它:

Cash cash(500.0);

BuySomething(cash);

// You can still use explicit casting:
BuySomething(static_cast<double>(cash));
BuySomething((double)cash);
BuySomething(double(cash));
BuySomething(double{ cash });

BuySomething(cash.operator double())

这是因为当编译器看到 BuySomething(cash); 时,它知道 BuySomething() 不接受 Cash - 它接受 double - 所以它不仅仅是抛出错误,而是试图找出一种将 Cash 转换为 double 的方法,并在此过程中找到我们的转换运算符。

如果您发现我的解释有问题,请在评论中告诉我。