使用operator关键字引入重载函数
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct Str
{
int val = 3;
};
struct Str2
{
};
Str Add(Str x, Str y)
{
Str z;
z.val = x.val + y.val;
return z;
}
auto operator + (Str x, Str y)
{
Str z;
z.val = x.val + y.val;
return z;
}
auto operator + (Str2 x, Str2 y)
{
}
int main()
{
Str x;
Str y;
Str z = x + y;
cout << z.val << endl;
}
重载不能发明新的运算,重载的一定是已经存在的运算。 不能改变运算的优先级与结合性。虽然我们可以定义运算的具体行为,但是不改变优先级和结合性。 通常不改变运算含义,比如本来是加号,不要内部改为-的含义。这样对使用者不友好。
函数参数个数与运算操作数个数相同,至少一个为类类型 除 operator() 外其它运算符不能有缺省参数,因为()里面对于个数没有要求。 可以选择实现为成员函数与非成员函数 通常来说,实现为成员函数会以 *this 作为第一个操作数(注意 == 与 <=> 的重载)
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct Str
{
int val = 3;
auto operator () (int y = 100)
{
return val + y;
}
auto operator + (Str x)
{
Str res;
res.val = val + x.val;
return res;
}
};
int main()
{
Str x;
cout << x(5) << endl;
Str a;
Str b;
b.val = 10;
Str c = a + b;
cout << c.val << endl;
}
运算符的进一步划分
根据重载特性,可以将运算符进一步划分 上面的运算符都是可以重载的。
- 可重载且必须实现为成员函数的运算符( =,[],(),-> 与转型运算符)
- 可重载且可以实现为非成员函数的运算符
- 可重载但不建议重载的运算符( &&, ||, 逗号运算符)C++17 中规定了相应的求值顺序但没有方式实现短路逻辑
- 不可重载的运算符(如 ? :运算符)
运算符重载——详述1
对称运算符通常定义为非成员函数以支持首个操作数的类型转换
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct Str
{
Str(int x)
: val(x)
{}
int val;
};
auto operator + (Str input1, Str input2)
{
return Str(input1.val + input2.val);
}
int main()
{
Str x = 3;
Str y = 4;
Str z1 = x + y;
Str z2 = x + 4;
Str z3 = 4 + x;
}
移位运算符一定要定义为非成员函数,因为其首个操作数类型为流类型
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct Str
{
Str(int x)
: val(x)
{}
friend auto& operator << (std::ostream& ostr, Str input)
{
ostr << input.val;
return ostr;
}
private:
int val;
};
int main()
{
Str x = 3;
Str y = 4;
cout << x << y;
}
赋值运算符也可以接收一般参数
#include <iostream>
#include <string>
#include <vector>
#include <string>
using namespace std;
struct Str
{
Str(int x)
: val(x)
{}
Str& operator = (const Str& input)
{
val = input.val;
return *this;
}
Str& operator = (const std::string input)
{
val = static_cast<int>(input.size());
return *this;
}
friend auto& operator << (std::ostream& ostr, Str input)
{
ostr << input.val;
return ostr;
}
int val;
};
int main()
{
Str x = 3;
x = "12345";
cout << x.val;
}
operator [] 通常返回引用,来模拟数组的访问
#include <iostream>
#include <string>
#include <vector>
#include <string>
using namespace std;
struct Str
{
Str(int x)
: val(x)
{}
Str& operator = (const Str& input)
{
val = input.val;
return *this;
}
Str& operator = (const std::string input)
{
val = static_cast<int>(input.size());
return *this;
}
friend auto& operator << (std::ostream& ostr, Str input)
{
ostr << input.val;
return ostr;
}
int& operator[] (int id)
{
return val;
}
int operator[] (int id) const
{
return val;
}
int val;
};
int main()
{
Str x = 3;
x = "12345";
cout << x[0] << endl;
x[0] = 100;
cout << x[0] << endl;
const Str cx = 11;
cout << cx[0] << endl;
}
自增、自减运算符的前缀、后缀重载方法 怎么来判断是前缀自增++x或者x++后缀自增呢?
#include <iostream>
#include <string>
#include <vector>
#include <string>
using namespace std;
struct Str
{
Str(int x)
:val(x)
{}
Str& operator = (const Str& input)
{
val = input.val;
return *this;
}
Str& operator = (const std::string input)
{
val = static_cast<int>(input.size());
return *this;
}
Str& operator++ ()
{
val += 100;
return *this;
}
Str operator++ (int)
{
Str tmp(*this);
val += 10;
return tmp;
}
int val;
};
int main()
{
Str s(3);
cout << (++s).val << endl;
int y = s++.val;
cout << y << endl;
cout << s.val << endl;
}
能使用前缀自增自减,就使用前缀,不使用后缀的 使用解引用运算符( * )与成员访问运算符( -> )模拟指针行为 .运算符一般是用于成员对象的对象.x,对象.fun(); ->一般是用于指针的,对象指针->x, 对象指针->fun(); .不能重载,->可以重载
#include <iostream>
#include <string>
#include <vector>
#include <string>
using namespace std;
struct Str
{
Str(int* p)
: ptr(p)
{
}
int& operator * ()
{
return *ptr;
}
Str* operator -> ()
{
return this;
}
int val = 5;
private:
int* ptr;
};
int main()
{
int x = 100;
Str ptr(&x);
cout << ptr->val << endl;
}
使用函数调用运算符构造可调用对象,接收参数个数不定
#include <iostream>
#include <string>
#include <vector>
#include <string>
using namespace std;
struct Str
{
Str(int p)
: val(p)
{}
int operator() ()
{
return val;
}
int operator() (int x, int y, int z)
{
return val + x + y + z;
}
private:
int val;
};
int main()
{
Str obj(100);
cout << obj() << endl;
cout << obj(1, 2, 3) << endl;
}
运算符重载——详述2
类型转换运算符
类型转换运算符,把一种类型转换成另外一种类型。
#include <iostream>
#include <string>
#include <vector>
#include <string>
using namespace std;
struct Str
{
Str(int p)
: val(p)
{}
operator int() const
{
return val;
}
private:
int val;
};
int main()
{
Str obj(100);
int v = obj;
cout << v << endl;
}
与单参数构造函数一样,都引入了一种类型转换方式
注意避免引入歧义性与意料之外的行为 通过 explicit 引入显式类型转换
#include <iostream>
#include <string>
#include <vector>
#include <string>
using namespace std;
struct Str
{
explicit Str(int p)
: val(p)
{}
operator int() const
{
return val;
}
friend auto operator + (Str a, Str b)
{
return Str(a.val + b.val);
}
private:
int val;
};
int main()
{
Str obj(100);
obj + 3;
}
explicit bool 的特殊性:用于条件表达式时会进行隐式类型转换
#include <iostream>
#include <string>
#include <vector>
#include <string>
using namespace std;
struct Str
{
explicit Str(int p)
: val(p)
{}
explicit operator bool() const
{
return (val == 0);
}
private:
int val;
};
int main()
{
Str obj(100);
auto var = obj ? 1 : 0;
cout << var << endl;
if (obj)
{
cout << 1 << endl;
}
else
{
cout << 0 << endl;
}
}
C++ 20 中对 == 与 <=> 的重载
#include <iostream>
#include <string>
#include <vector>
#include <string>
using namespace std;
struct Str
{
explicit Str(int p)
: val(p)
{}
friend bool operator == (Str obj, Str obj2)
{
return obj.val == obj2.val;
}
private:
int val;
};
int main()
{
Str obj(100);
Str obj2(100);
cout << (obj == obj2) << endl;
cout << (obj != obj2) << endl;
}
注意 <=> 可返回的类型: strong_ordering, week_ordering, partial_ordering
|