C++运算符重载模仿管道操作
重载 + 运算
实现+运算重载
通过类内部实现成员函数operator+
以重载成员运算符+
,并接受一个右操作数为int
类型。返回自己的引用。
class A
{
public:
A(int v) : _v(v)
{}
A& operator+(int v)
{
_v += v;
return *this;
}
A& operator+(const A& rhs)
{
_v += rhs._v;
return *this;
}
private:
int _v = 0;
};
int main()
{
A a(1);
(a + 1) + a; // 4
return 0;
}
首先程序进行计算a+1
返回A类型,然后进行(a+a)
那么考虑一个问题,我们的类型A
的加法支持交换律吗,也就是
(1 + a) + a;//?
显然不支持。因为我们没有定义一个做操作数为数字而有操作数是类型A
的行为,那么如何解决呢?
友元函数
一般情况下,单目运算符最好重载为类的成员函数;双目运算符则最好重载为类的友元函数,类中定义的友元函数,它不是成员函数,但它拥有成员函数的访问权限。基本定义格式如下:
friend int operator+(int lhs, const A& rhs)
{
// 访问类成员
return lhs + rhs._v;
}
使用成员函数重载运算符时,第一个操作数通过this指针隐式地传递,而友元函数不是成员函数,所以要有两个参数且是显示的传递。
完整代码如下:
class A
{
public:
A(int v) : _v(v)
{}
A& operator+(int v)
{
_v += v;
return *this;
}
A& operator+(const A& rhs)
{
_v += rhs._v;
return *this;
}
friend int operator+(int lhs, const A& rhs)
{
// 访问类成员
return lhs + rhs._v;
}
private:
int _v = 0;
};
int main()
{
A a(1);
int v = (1 + a) + a;
return 0;
}
全局运算符重载探索
我们只是简仿C++20
的ranges
操作,不要用于实际。
我们想实现一个功能,类似与管道操作符,对一个字符串的一个操作的结果能给下一个使用。比如:
#include <iostream>
#include <ranges>
#include <vector>
#include <ranges>
#include <iostream>
template <typename T, typename F>
std::vector<T> operator|(std::vector<T> vec, F &&f)
{
return f(vec);
}
namespace views
{
template <typename F>
class filter
{
public:
filter(const F &f) : f_(f)
{
}
std::vector<int> operator()(const std::vector<int> &data)
{
std::vector<int> new_data;
for (const auto &d : data)
{
if (f_(d))
{
new_data.push_back(d);
}
}
return new_data;
}
private:
const F &f_;
};
template <typename F>
class transform
{
public:
transform(const F &f) : f_(f)
{
}
std::vector<int> operator()(const std::vector<int> &data)
{
std::vector<int> new_data;
for (const auto &d : data)
{
new_data.push_back(f_(d));
}
return new_data;
}
private:
const F &f_;
};
}
int main()
{
auto even = [](int i)
{ return 0 == i % 2; };
auto square = [](int i)
{ return i * i; };
std::vector<int> data = {0, 1, 2, 3, 4, 5};
const auto ret = data | views::filter(even) | views::transform(square);
// const auto ret = data | [even](const std::vector<int> &data)
// {
// std::vector<int> new_data;
// for (const auto &d : data)
// {
// if (even(d))
// {
// new_data.push_back(d);
// }
// }
// return new_data;
// };
for (const auto &d : ret)
{
std::cout << d << " ";
}
return 0;
// 组合视图的“管道”语法:
// for (int i : data | std::views::filter(even) | std::views::transform(square)) {
// std::cout << i << ' ';
// }
// std::cout << '\n';
// // 传统的“函数式”组合语法:
// for (int i : std::views::transform(std::views::filter(data, even), square)) {
// std::cout << i << ' ';
// }
}