运算符重载 operator overloading

最近重新复习一下C++的一些基础概念,加深一下自己的理解 主要是藉由一本老书《Advanced C++ programming styles and idioms》 by James O. Coplien 同时借助ChatGPT的帮助,拓展一些更深入广泛的话题
之前对类型转换,只是局限在有限的理解上,比如C传统的强制类型转换, 隐式的类型转换(具体什么场景,并没有特别关注,多数是内建的类型之间,这个都由编译器自行处理了)
对于C++自定义类型相互转换,我有个问题,自定义类型 A 与 B 之间类型如何相互转换的?场景有哪些?类型转化运算符重载? 比如两个自定义类A 和 B 之间的转化,这个转化运算符该由谁实现? 比如是A 还是B?抑或是双向的?
类型转换运算符可以由类 A 或类 B 中的任意一个实现,取决于转换的方向和设计需求。
- 如果是从 A 到 B 的转换:
如果你希望在类型 A 中实现对类型 B 的转换,你可以在类 A 中重载类型转换运算符,以便从 A 类型的对象转换为 B 类型的对象。这样的话,在使用时,你就可以直接将 A 类型的对象转换为 B 类型。 如果你认为类型转换更适合在类 B 中实现,你也可以在类 B 中定义一个接受类型 A 的构造函数,并将其标记为 explicit,以防止隐式转换。这样的话,你就可以在需要时显式地将 A 类型的对象传递给 B 类型的构造函数。
- 如果是从 B 到 A 的转换:
类似地,如果你希望在类型 B 中实现对类型 A 的转换,你可以在类 B 中重载类型转换运算符,以便从 B 类型的对象转换为 A 类型的对象。 如果你认为类型转换更适合在类 A 中实现,你可以在类 A 中定义一个接受类型 B 的构造函数,并将其标记为 explicit,以防止隐式转换。
总之,实现类型转换运算符应该遵循设计的一致性和可读性原则。在决定转换的方向和实现位置时,考虑代码的清晰性、易用性以及你的设计目标。
具体代码展示很容易理解
自定义类型A, B 下面这个例子,A和B内部分别是int和double类型的变量value
#include <iostream>
class B; // 前置声明类 B
class A {
private:
int value;
public:
A(int v) : value(v) {}
// 类型转换运算符:从 A 到 B
operator B() const; // 在类 A 中定义该运算符,这里只进行声明
// 类型转换运算符:从 A 到 int
operator int() const {
return value; // 将 A 类型的 value 直接转换为 int 类型
}
};
class B {
private:
double value;
public:
B(double v) : value(v) {}
// 类型转换运算符:从 B 到 A
operator A() const {
return A(static_cast<int>(value)); // 将 double 类型的 value 转换为 int,并传递给 A 类的构造函数
}
// 类型转换运算符:从 B 到 double
operator double() const {
return value; // 将 B 类型的 value 直接转换为 double 类型
}
};
// 类型转换运算符的定义:从 A 到 B
A::operator B() const {
return B(static_cast<double>(value)); // 将 int 类型的 value 转换为 double,并传递给 B 类的构造函数
}
A和B内部分别定义了int和double的转换运算符,将A到int,B到double转换 同时A和B内部也分别定义了A到B,B到A的转换运算符
使用例子:
int main() {
A a_obj(5);
// 类型转换在 A 类和 B 类中实现
B b_obj = a_obj; // 隐式转换
double value_b = b_obj; // 隐式转换
std::cout << "Value of b_obj (B type): " << value_b << std::endl;
B b_obj2(3.14);
A a_obj2 = b_obj2; // 隐式转换
int value_a = a_obj2; // 隐式转换
std::cout << "Value of a_obj (A type): " << value_a << std::endl;
return 0;
}
消除int和double的隐式转换,直接A和B之间的转换
#include <iostream>
class B; // 前置声明类 B
class A {
private:
int value;
public:
A(int v) : value(v) {}
// 类型转换运算符:从 A 到 B
operator B() const; // 在类 B 中定义该运算符,这里只进行声明
};
class B {
private:
int value;
public:
B(int v) : value(v) {}
// 类型转换运算符:从 B 到 A
operator A() const {
return A(value); // 将 B 类型的 value 直接传递给 A 类的构造函数
}
};
// 类型转换运算符的定义:从 A 到 B
A::operator B() const {
return B(value); // 将 A 类型的 value 直接传递给 B 类的构造函数
}
int main() {
A a_obj(5);
// 类型转换在 A 类和 B 类中实现
B b_obj = a_obj; // 隐式转换
// 使用 b_obj 变量来消除编译警告
//std::cout << "Value of b_obj (B type): " << static_cast<int>(b_obj) << std::endl;
// [&b_obj] {
// (void)b_obj; // 使用 (void) 强制将变量转换为 void 类型,以消除编译警告
// }();
(void)b_obj;
return 0;
}
A, B 类型转换运算符直接返回需要的对象类型
自定义类,禁止隐式类型转换
使用explicit关键字
// 使用 explicit 关键字来防止隐式类型转换
class MyType {
public:
explicit MyType(int val) : value(val) {}
private:
int value;
};

评论