c++ - 显式转换运算符与同一类中的第二个隐式转换运算符的危险
问题描述
我发现自己处于一种情况,我很想将两个转换运算符放在一个类中。通常我会像避免瘟疫一样避免这种情况。但是使用 C++ 11 和显式转换运算符,我想要实现的似乎既合理又安全。但是我需要一个健全性检查。
考虑以下类(“距离”),旨在将距离值与其测量单位联系在一起。
enum class Unit { None = 0, Meter = 1, Foot = 2, }; // None means INVALID
class Distance
{
Unit m_unit;
double m_value;
public:
Distance() : m_unit(Unit::None), m_value(0.f) {} // construct invalid
Distance(Unit u, double, v) : m_unit(u), m_value(v) {}
Unit unit() const { return m_unit; }
// Two functions that I would like to make into cast operators:
double value() const { return m_value; }
bool valid() const { return Unit::None != m_unit; }
// Cast operators I would LIKE to add and use. Implicitly cast to
// double but in "if()" scenarios, cast to bool to check validity
operator double() const { return m_value; }
explicit operator bool() { return valid(); }
};
由于 Distance 对象应该被视为一个双精度值(大多数情况下),因此我考虑添加隐式双精度转换(上图)。但是在某些情况下,距离可以被认为是“无效的”,由 Unit::None 的单位值表示。在那种情况下,我真的很喜欢添加显式布尔转换的想法。
最终目标是能够替换当前如下所示的代码:
void doSomething(bool b) {}
void doSomething(double d) {}
void DumpDistance(const Distance& dist)
{
if (dist.valid())
std::cout << dist.value() << std::endl;
doSomething(dist.valid()); // properly calls bool version
doSomething(dist.value()); // properly called double version
}
进入这个:
void DumpDistance(const Distance& dist)
{
if (dist) // treated as bool (good)
std::cout << dist << std::endl; // treated as double (good)
doSomething(dist); // calls double overload (good)
}
在我的测试中,显式布尔运算符似乎可以解决问题。但我不确定。看起来正在调用所需的重载。但在 1990 年代黑暗的过去,我对选角操作员有一种内在的厌恶。
所以我的问题:
这真的像看起来那样安全吗? 是否有一些我遗漏的明显情况,编译器会抱怨转换不明确,或者更糟糕的是,当我想要另一个运算符时,会默默地调用一个运算符?
(要清楚:我不是在问这个的必要性,也不是关于它的可读性。只是关于编译时歧义或我不想发生的转换的危险。我需要巩固显式转换运算符的概念我的头。 )
解决方案
推荐阅读
- sharepoint - Office 365 Management Activity API - Audit.SharePoint returns event out of the time frame
- python - ORM中创建或调用类的区别
- r - 图的一侧显示第二组/类别的条形图
- oracle - JPA em.find(id) 适用于 Oracle 但不适用于 MariaDB
- microsoft-graph-api - Microsoft Graph Api 中的 List-Unsubscribe 标头不起作用
- powershell - 在 Powershell 中对路径列表进行排序
- tomcat - Apache Tomcat 服务器在注销时关闭
- python-3.x - 使用 aiohttp 创建非阻塞 RESTful 服务
- scala - scala.util.Try 递归函数抛出编译错误
- javascript - 如何将类构造函数的前一个实例的参数传播到另一个实例