1、operator作类的转换函数
类可以使用构造函数将其他类型转化为此类的对象,比如
my_class a = my_class(int i);
将int型转化为my_class类的一个对象。
同样,也可以使用类的转换函数将类的对象转化为其他的类型。
类的转换函数应当满足以下的几个条件:
- 转换函数必须是类方法
- 转换函数不能指定返回类型
- 转换函数不能有参数
下面是一个类转化函数的例子
#include <iostream>
using namespace std;
class my_class
{
public:
operator int()//定义了一个将类转化为int的转换函数
{
cout << "convert_to_int" << endl;
return 1;
}
};
int main()
{
my_class a;
int i_a = (int)a;//第一次显式的转换
cout << a << endl;//第二次隐式的转换
return 0;
}
当然也可以转化为任意其他的类型(int,double,float,bool),只需要改变转换函数即可。
但是在定义转化函数时,要避免出现二义性,比如不要同时提供多个符合条件的转换函数:
#include <iostream>
using namespace std;
class my_class
{
public:
operator double()//定义了一个将类转化为double的转换函数
{
cout << "convert_to_double" << endl;
return 1.1;
}
operator int()//定义了一个将类转化为int的转换函数
{
cout << "convert_to_int" << endl;
return 1;
}
};
int main()
{
my_class a;
cout << a << endl;//报错
return 0;
}
在VS上得到如下的报错信息:
有多个运算符 "<<" 与这些操作数匹配
当然,若同时需要这两个转换函数,这个错误也可以通过很多方法来解决,比如显式的指定要输出的是哪种类型,而不是让编译器自己去选择:
cout << (double)a << endl;
或者指定其中一个转换函数只能显式的转换,而不能隐式的转换,使用explicit关键字
explicit operator double()
{
cout << "convert_to_double" << endl;
return 1.1;
}
explicit(显式)关键字
explicit 修饰构造函数时,可以防止隐式转换和复制初始化
explicit 修饰转换函数时,可以防止隐式转换,但 按语境转换 除外
struct A
{
A(int) { }
operator bool() const { return true; }
};
struct B
{
explicit B(int) {}
explicit operator bool() const { return true; }
};
void doA(A a) {}
void doB(B b) {}
int main()
{
A a1(1); // OK:直接初始化
A a2 = 1; // OK:复制初始化
A a3{ 1 }; // OK:直接列表初始化
A a4 = { 1 }; // OK:复制列表初始化
A a5 = (A)1; // OK:允许 static_cast 的显式转换
doA(1); // OK:允许从 int 到 A 的隐式转换
if (a1); // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换
bool a6(a1); // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换
bool a7 = a1; // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换
bool a8 = static_cast<bool>(a1); // OK :static_cast 进行直接初始化
B b1(1); // OK:直接初始化
B b2 = 1; // 错误:被 explicit 修饰构造函数的对象不可以复制初始化
B b3{ 1 }; // OK:直接列表初始化
B b4 = { 1 }; // 错误:被 explicit 修饰构造函数的对象不可以复制列表初始化
B b5 = (B)1; // OK:允许 static_cast 的显式转换
doB(1); // 错误:被 explicit 修饰构造函数的对象不可以从 int 到 B 的隐式转换
if (b1); // OK:被 explicit 修饰转换函数 B::operator bool() 的对象可以从 B 到 bool 的按语境转换
bool b6(b1); // OK:被 explicit 修饰转换函数 B::operator bool() 的对象可以从 B 到 bool 的按语境转换
bool b7 = b1; // 错误:被 explicit 修饰转换函数 B::operator bool() 的对象不可以隐式转换
bool b8 = static_cast<bool>(b1); // OK:static_cast 进行直接初始化
return 0;
}
2、operator在类中重载运算符
重载与类型转换虽然使用的是同一个关键字,但它们在形式上还是有很大的差别的:
类型转换:operator <类型>()
运算符重载:<类型> operator <运算符>(<参数表>)
重载主要有两种形式,成员函数形式与友元函数形式。下面举个例子:
#include <iostream>
using namespace std;
class MyClass
{
public:
MyClass() {}
MyClass(int a, double b):a_(a),b_(b){}
~MyClass(){}
int get_a() { return a_; }
double get_b() { return b_; }
MyClass operator+(const MyClass &adder) const//以成员函数方式重载+
{
MyClass sum;
sum.a_ = a_ + adder.a_;
sum.b_ = b_ + adder.b_;
return sum;
}
friend MyClass operator-(const MyClass &A,const MyClass &B)//以友元方式重载-
{
MyClass diff;
diff.a_ = A.a_ - B.a_;
diff.b_ = A.b_ - B.b_;
return diff;
}
private:
int a_;
double b_;
};
int main()
{
MyClass A(1, 1.1);
MyClass B(2, 2.2);
MyClass sum = A + B;
MyClass diff = A - B;
cout << sum.get_a() << "\t" << sum.get_b() << endl;
cout << diff.get_a() << "\t" << diff.get_b() << endl;
return 0;
}