如何在C++17中创建可自动钳位0.0-360.0的类类型(行为同double)
解决方案
完整实现代码
#include <iostream> #include <algorithm> // 用于std::clamp(C++17支持) class degree { private: double value; // 静态辅助函数:钳位值到[0.0, 360.0] static double clamp(double val) { return std::clamp(val, 0.0, 360.0); } public: // 构造函数:初始化时钳位 degree(double val = 0.0) : value(clamp(val)) {} // 拷贝构造与移动构造 degree(const degree& other) = default; degree(degree&& other) = default; // 赋值运算符:处理double和degree类型的赋值,都钳位 degree& operator=(double val) { value = clamp(val); return *this; } degree& operator=(const degree& other) = default; degree& operator=(degree&& other) = default; // 隐式转换为double,无需getter operator double() const { return value; } // 算术运算符重载:运算后钳位 degree operator+(double val) const { return degree(value + val); } degree operator-(double val) const { return degree(value - val); } degree operator*(double val) const { return degree(value * val); } degree operator/(double val) const { return degree(value / val); } // 与degree类型的运算 degree operator+(const degree& other) const { return degree(value + other.value); } degree operator-(const degree& other) const { return degree(value - other.value); } degree operator*(const degree& other) const { return degree(value * other.value); } degree operator/(const degree& other) const { return degree(value / other.value); } // 复合赋值运算符 degree& operator+=(double val) { value = clamp(value + val); return *this; } degree& operator-=(double val) { value = clamp(value - val); return *this; } degree& operator*=(double val) { value = clamp(value * val); return *this; } degree& operator/=(double val) { value = clamp(value / val); return *this; } degree& operator+=(const degree& other) { value = clamp(value + other.value); return *this; } degree& operator-=(const degree& other) { value = clamp(value - other.value); return *this; } degree& operator*=(const degree& other) { value = clamp(value * other.value); return *this; } degree& operator/=(const degree& other) { value = clamp(value / other.value); return *this; } }; // 重载输出运算符,方便打印 std::ostream& operator<<(std::ostream& os, const degree& deg) { os << static_cast<double>(deg); return os; } int main() { degree my_num1 = 3.5; std::cout << "my_num1 = " << my_num1 << "\n"; // 输出3.5 degree my_num2 = 400.8; std::cout << "my_num2 = " << my_num2 << "\n"; // 输出360.0 degree my_num3 = -5.1; std::cout << "my_num3 = " << my_num3 << "\n"; // 输出0.0 my_num3 = my_num2 - my_num1; std::cout << "my_num3 = my_num2 - my_num1 = " << my_num3 << "\n"; // 输出356.5 // 额外测试复合赋值 my_num3 += 10.0; std::cout << "my_num3 +=10.0 = " << my_num3 << "\n"; // 输出360.0 my_num3 -= 400.0; std::cout << "my_num3 -=400.0 = " << my_num3 << "\n"; // 输出0.0 return 0; }
关键部分解释
- 钳位逻辑:借助C++17标准库的
std::clamp函数,一键实现值的范围限制,确保所有操作后的结果都落在0.0到360.0之间。 - 隐式转换到double:通过
operator double() const重载,让degree对象可以直接当作double使用,比如直接输出、参与其他double类型的运算,完全不需要getter方法。 - 构造与赋值处理:所有构造函数和赋值运算符都会先对输入值进行钳位,保证对象从创建到修改的每一步,内部值都合法。
- 完整运算符重载:覆盖了常用的算术运算符(+、-、*、/)和复合赋值运算符(+=、-=等),同时支持
degree与degree、degree与double之间的运算,运算结果自动钳位,让degree的使用体验和原生double几乎一致。 - 简化实现:不需要模板,因为我们只需要封装
double类型,去掉不必要的泛型逻辑,代码更简洁易懂。
测试验证
运行上述代码后,输出结果完全符合预期:
my_num1 = 3.5 my_num2 = 360 my_num3 = 0 my_num3 = my_num2 - my_num1 = 356.5 my_num3 +=10.0 = 360 my_num3 -=400.0 = 0
内容的提问来源于stack exchange,提问作者Invader88
相关产品推荐
相关产品推荐

