Date类重载比较与bool转换运算符时出现调用错误求助
C++ Date类比较运算符被bool转换运算符劫持
我编写了Date类并重载了比较运算符,但运行测试代码时,比较操作没有调用对应的重载函数,反而触发了operator bool()的隐式转换。
类定义代码
class Date { private: int m_year; int m_mon; int m_day; int m_ErrorCode; int m_CUR_YEAR; int daysSince0001_1_1()const; // 返回自0001/1/1以来的天数 bool validate(); /* 验证日期,设置错误码并返回结果: 有效返回true,无效返回false */ void errCode(int); // 设置错误码 int systemYear()const; // 返回当前系统年份 bool bad()const; // 若日期无效返回true int mdays()const; // 返回当前月份的天数 void setToToday(); // 将日期设置为系统当前日期 public: Date(); // 创建当前日期的对象 Date(int year, int mon, int day); /* 用指定值创建日期对象, 验证日期并设置错误码 */ int errCode()const; // 返回错误码,日期有效则返回0 const char* dateStatus()const; // 返回描述当前日期状态的字符串 int currentYear()const; // 返回m_CUR_YEAR的值; bool operator==(Date& date) const; bool operator!=(Date& date) const; bool operator>=(Date& date) const; bool operator<=(Date& date) const; bool operator<(Date& date) const; bool operator>(Date& date) const; int operator-(Date& date) const; operator bool() const; std::istream& read(std::istream& is = std::cin); std::ostream& write(std::ostream& os = std::cout)const; };
类实现代码
bool Date::bad()const { return m_ErrorCode != 0; } bool Date::operator==(Date& date) const { return daysSince0001_1_1() == date.daysSince0001_1_1(); } bool Date::operator!=(Date& date) const { return daysSince0001_1_1() != date.daysSince0001_1_1(); } bool Date::operator>=(Date& date) const { return daysSince0001_1_1() >= date.daysSince0001_1_1(); } bool Date::operator<=(Date& date) const { return daysSince0001_1_1() <= date.daysSince0001_1_1(); } bool Date::operator<(Date& date) const { return daysSince0001_1_1() < date.daysSince0001_1_1(); } bool Date::operator>(Date& date) const { return daysSince0001_1_1() > date.daysSince0001_1_1(); } int Date::operator-(Date& date) const { return daysSince0001_1_1() - date.daysSince0001_1_1(); } Date::operator bool() const { return !bad(); }
测试代码
if (B > A) { cout << B << " > " << A << endl; } else { cout << B << " <= " << A << endl; } if (B < A) { cout << B << " < " << A << endl; } else { cout << B << " >= " << A << endl; } if (B <= A) { cout << B << " <= " << A << endl; } else { cout << B << " > " << A << endl; } if (B >= A) { cout << B << " >= " << A << endl; } else { cout << B << " < " << A << endl; } if (B == A) { cout << B << " == " << A << endl; } else { cout << B << " != " << A << endl; } if (B != A) { cout << B << " != " << A << endl; } else { cout << B << " == " << A << endl; } cout << "Days between the two dates: " << B - A << endl;
问题原因与解决方案
核心原因
- 比较运算符参数未使用const引用:当前比较运算符的参数是
Date&(非const左值引用),如果测试中的A、B是const对象或临时对象,编译器无法将其绑定到非const引用,此时会触发隐式转换——把Date对象通过operator bool()转成bool类型,再进行整数比较(bool会被提升为int)。即使A、B是非const对象,编译器的重载解析逻辑也可能优先选择转换路径。 - operator bool()是隐式转换:未加
explicit修饰的operator bool()会允许编译器进行自动隐式转换,这是导致比较操作被劫持的关键诱因。
修复步骤
1. 修改比较运算符的参数为const引用
将类声明和实现中的所有比较运算符(包括operator-)的参数改为const Date&,因为比较操作不会修改参数,同时这样的参数可以接受const对象、非const对象和临时对象,匹配所有场景:
修改后的类声明:
bool operator==(const Date& date) const; bool operator!=(const Date& date) const; bool operator>=(const Date& date) const; bool operator<=(const Date& date) const; bool operator<(const Date& date) const; bool operator>(const Date& date) const; int operator-(const Date& date) const;
修改后的实现示例:
bool Date::operator==(const Date& date) const { return daysSince0001_1_1() == date.daysSince0001_1_1(); } int Date::operator-(const Date& date) const { return daysSince0001_1_1() - date.daysSince0001_1_1(); }
2. 给operator bool()添加explicit修饰(推荐)
在C++11及以后的标准中,给operator bool()加上explicit关键字,禁止编译器进行隐式转换,从根源避免这类劫持问题:
类声明修改:
explicit operator bool() const;
实现部分无需修改,保持原有逻辑即可。
修复效果
修改完成后,编译器会优先匹配正确的比较运算符重载,不会再触发operator bool()的隐式转换,测试代码会按照预期调用对应的比较函数。
内容的提问来源于stack exchange,提问作者Khaled Bais
相关产品推荐
相关产品推荐

