关于在转换操作符中使用显式关键字的警告

所以我有一个名为 Date 它看起来像这样。

class Date {
private:
    UINT month, day, year;
    std::string DateToString;
public:
    Date(UINT inMonth, UINT inDay, UINT inYear)
    : month(inMonth), day(inDay), year(inYear){}

    operator PCSTR() {
        //essentially just an ostream that takes strings inside it
        std::ostringstream formattedDate;
        //feed it and convert integers as well
        formattedDate << this->month << " / " << this->day << " / " << this->year;

        //get content of stream as a pointer with str() method
        //store the pointer in local var to avoid it to being invalidated after RET was hit and cout not able to display
        this->DateToString = formattedDate.str();
        return DateToString.c_str();//convert that ostringstream string to a PCSTR
    }
}

注意:我使用的是Windows的数据类型,其中包括 PCSTR 作为 const char* 和UINT一个 unsigned int.

现在这个类作为一个日期实例化类。Date test(1, 10, 2020),我已经创建了 operator PCSTR() 成员方法,以便能够在 cout,因为后者将使用最适合的操作符转换来能够显示一个对象,这里我们使用的是 const char*/PCSTR 因为 cout 不存在任何显示问题。所以如果我做 cout << test; 它显示 1/10/2020.

现在在我的代码编辑器中,它告诉我 'operator const char *' must be marked explicit to avoid unintentional implicit conversions,我不明白,这不是我们想要的吗,如果我把它标记为显式,那么我就必须投出对象,为什么我不能就这样离开呢?还有哪些转换可以通过 const char*?

先谢谢你。

4
投票

我可以想到这里有一个无意的隐式转换。如果你不小心写了

Date date;
// ...
if (date) { /* ... */ }

编译器可以先将 dateconst char*,然后 const char*bool,这将是一个难以调试的局面。在 explicit 操作符可以防止这种情况。

有一个更好的方法来定义你的类应该如何被打印到 std::cout:

class Date {
  // ...
  std::string toString() const {
    // ...
    return formattedDate.str();
  }
}

std::ostream& operator<<(std::ostream& out, const Date& date) {
  return out << date.toString();
}

如果你必须使用转换操作符,为什么不把它明确化,在需要的地方进行转换?这将更容易从代码中看到到底发生了什么。

std::cout << static_cast<const char*>(date);
1
投票

现在在我的代码编辑器中,它告诉我'operator const char *'必须标记为显式,以避免无意的隐式转换。

没错,就是这样 这只是一个警告,但这是一个很好的警告!

我不明白,这不正是我们想要的吗?

不!

如果我把它标记为显式,那么我就必须把对象投给

这是件好事。它避免了意外。

为什么我不能就这样离开呢?

如果你愿意,你可以这样做。但我建议你不要这样做