网站快速排名怎么做,手机房屋3d设计软件,华为商城app,生产做网站表带的制造厂家目录
前言
算术运算符重载
加号运算符
位运算符重载
左移运算符
自增自减运算符重载
前置自增运算符
后置自增运算符
赋值运算符重载
等号赋值运算符重
关系运算符重载
相等
不等
函数调用运算符重载
总结 前言 在C中#xff0c;运算符重载是一种强大的特性…目录
前言
算术运算符重载
加号运算符
位运算符重载
左移运算符
自增自减运算符重载
前置自增运算符
后置自增运算符
赋值运算符重载
等号赋值运算符重
关系运算符重载
相等
不等
函数调用运算符重载
总结 前言 在C中运算符重载是一种强大的特性允许您重新定义已定义的运算符以便它们适用于用户自定义类型。通过运算符重载您可以编写自定义类型的运算符行为使得用户自定义类型的对象可以像内置类型一样进行运算。
算术运算符重载 执行加法操作通常用于数字或字符串的拼接。-执行减法操作通常用于数字之间的减法运算。*执行乘法操作通常用于数字之间的乘法运算。/执行除法操作通常用于数字之间的除法运算。 通过重载这些算术运算符您可以定义自定义类型对象之间的加减乘除操作。这使得用户自定义类型的对象可以像内置类型一样进行算术运算。 加号运算符
#include iostream
using namespace std;class Person {
public:Person() {};Person(int a, int b){this-m_A a;this-m_B b;}// 成员函数实现 号运算符重载Person operator(const Person p) {Person temp;temp.m_A this-m_A p.m_A;temp.m_B this-m_B p.m_B;return temp;}public:int m_A;int m_B;
};// 全局函数实现 号运算符重载
//Person operator(const Person p1, const Person p2) {
// Person temp(0, 0);
// temp.m_A p1.m_A p2.m_A;
// temp.m_B p1.m_B p2.m_B;
// return temp;
//}// 运算符重载 可以发生函数重载就是可以根据参数的不同去分别调用不同的operator运算符重载函数
Person operator(const Person p2, int val)
{Person temp;temp.m_A p2.m_A val;temp.m_B p2.m_B val;return temp;
}void test() {Person p1(10, 10);Person p2(20, 20);// 成员函数方式Person p3 p2 p1; // 相当于 p2.operaor(p1)cout mA: p3.m_A mB: p3.m_B endl; // 30 30Person p4 p3 10; // 相当于 operator(p3,10)cout mA: p4.m_A mB: p4.m_B endl; // 40 40}int main() {test();return 0;
}
位运算符重载
按位与运算符对两个操作数逐位进行与运算。|按位或运算符对两个操作数逐位进行或运算。^按位异或运算符对两个操作数逐位进行异或运算。~按位取反运算符对操作数逐位取反。左移运算符将操作数的二进制位向左移动指定的位数。右移运算符将操作数的二进制位向右移动指定的位数。 通过重载位运算符您可以定义自定义类型对象之间的按位操作。这使得自定义类型的对象可以进行位级运算。 左移运算符
#include iostream
using namespace std;
#include string/* 作用可以输出自定义数据类型 */class Person {friend ostream operator(ostream out, Person p); // 全局函数做Person类的友元可以访问类的私有成员public:Person(int a, int b){this-m_A a;this-m_B b;}//成员函数 实现不了 p cout 不是我们想要的效果//void operator(Person p){//}private:int m_A;int m_B;
};//全局函数实现左移重载
//ostream对象只能有一个故使用 引用接收不会创建新对象
ostream operator(ostream out, Person p) { out a: p.m_A b: p.m_B;return out; // 需返回cout引用达到链式调用的效果
}void test() {Person p1(10, 20);cout p1 hello world endl; // a:10 b:20hello world 链式编程
}int main() {test(); // 重载左移运算符配合友元可以实现输出自定义数据类型return 0;
}
自增自减运算符重载 通过重载自增和自减运算符您可以定义自定义类型对象的自增和自减操作。这允许您使用和--来递增或递减对象的值。 前置自增运算符
前置必须返回引用不能返回值因为要对同一原对象操作 解释一下 test01函数中的 cout myInt endl。首先递增运算符的重载函数myInt会被执行将myInt的值加1并返回递增后的对象引用。然后左移运算符的重载函数operator会接受递增后的对象作为参数并将其输出到标准输出流cout中。
#include iostream
using namespace std;
#include stringclass MyInteger {friend ostream operator(ostream out, MyInteger myint);public:MyInteger() {m_Num 0;}//前置必须返回引用不能返回值因为要对同一原对象操作MyInteger operator() { //先this-m_Num;//再返回return *this;}private:int m_Num;
};/* 左移重载 */
ostream operator(ostream out, MyInteger myint) {out myint.m_Num;return out;
}// 前置 先 再返回
void test01() {class MyInteger myInt;cout myInt endl; // 1 递增重载、左移重载cout myInt endl; // 1 左移重载
}int main() {test01();return 0;
}
后置自增运算符
后置, 只能返回值因为创建的是临时对象函数销毁引用就不对了
#include iostream
using namespace std;
#include string/*前置递增返回引用后置递增返回值
*/class MyInteger {friend ostream operator(ostream out, MyInteger myint);public:MyInteger() {m_Num 0;}//后置, 只能返回值因为创建的是临时对象函数销毁引用就不对了MyInteger operator(int) { // int 代表后置 //先返回MyInteger temp *this; // 记录当前本身的值然后让本身的值加1但是返回的是以前的值达到先返回后this-m_Num;return temp; // 此时返回的还是前的 0}private:int m_Num;
};/* 左移重载 */
ostream operator(ostream out, MyInteger myint) {out myint.m_Num;return out;
}//后置 先返回 再
void test02() {MyInteger myInt;cout myInt endl; // 0cout myInt endl; // 1
}int main() {test02();return 0;
}
赋值运算符重载
将右操作数的值赋给左操作数。将左操作数与右操作数相加并将结果赋给左操作数。-将左操作数与右操作数相减并将结果赋给左操作数。*将左操作数与右操作数相乘并将结果赋给左操作数。/将左操作数与右操作数相除并将结果赋给左操作数。 通过重载赋值运算符您可以定义自定义类型的对象如何进行赋值操作。这使得对象可以通过使用等号和其他赋值运算符来进行赋值。 等号赋值运算符重
c编译器至少给一个类添加4个函数 默认构造函数(无参函数体为空)默认析构函数(无参函数体为空)默认拷贝构造函数对属性进行值拷贝赋值运算符 operator, 对属性进行值拷贝
如果类中有属性指向堆区做赋值操作时也会出现深浅拷贝问题
如果是浅拷贝不做赋值重载深拷贝那么每个类对象都会执行释放但已释放的空间二次释放就会报错
class Person
{
public:Person(int age){// 将年龄数据开辟到堆区m_Age new int(age);}// 重载赋值运算符 返回自身引用Person operator(Person p){if (m_Age ! NULL){delete m_Age;m_Age NULL;}// 编译器提供的代码是浅拷贝//m_Age p.m_Age;// 提供深拷贝 解决浅拷贝的问题m_Age new int(*p.m_Age); // 各自指向各自的空间//返回自身return *this;}~Person() // 析构函数{if (m_Age ! NULL){delete m_Age; // 如果是浅拷贝不做赋值重载深拷贝那么每个类对象都会执行释放同一个堆空间二次释放就会报错m_Age NULL;}}//年龄的指针int *m_Age;};void test01()
{Person p1(18);Person p2(20);Person p3(30);p3 p2 p1; // 连续赋值操作前提必须返回自身引用cout p1的年龄为 *p1.m_Age endl; // 18cout p2的年龄为 *p2.m_Age endl; // 18cout p3的年龄为 *p3.m_Age endl; // 18
}int main() {test01();//int a 10;//int b 20;//int c 30;//c b a;//cout a a endl;//cout b b endl;//cout c c endl;return 0;
}
关系运算符重载
检查两个值是否相等返回布尔值。!检查两个值是否不相等返回布尔值。检查左操作数是否大于右操作数返回布尔值。检查左操作数是否小于右操作数返回布尔值。检查左操作数是否大于或等于右操作数返回布尔值。检查左操作数是否小于或等于右操作数返回布尔值。 通过重载这些关系运算符您可以定义自定义类型对象之间的比较操作。这使得您可以使用关系运算符来比较自定义类型的对象并根据需要定义其比较规则。 相等
class Person
{
public:Person(string name, int age){this-m_Name name;this-m_Age age;};bool operator(Person p) // 关系重载相等{if (this-m_Name p.m_Name this-m_Age p.m_Age){return true;}else{return false;}}};void test01()
{//int a 0;//int b 0;Person a(孙悟空, 18);Person b(孙悟空, 18);if (a b){cout a和b相等 endl; // a和b相等}else{cout a和b不相等 endl;}}int main() {test01();return 0;
}
不等
#include iostream
using namespace std;
#include string/* 重载关系运算符可以让两个自定义类型对象进行对比操作 */class Person
{
public:Person(string name, int age){this-m_Name name;this-m_Age age;};bool operator!(Person p) // 关系重载不等{if (this-m_Name p.m_Name this-m_Age p.m_Age){return false;}else{return true;}}string m_Name;int m_Age;
};void test01()
{//int a 0;//int b 0;Person a(孙悟空, 18);Person b(孙悟空, 18);if (a ! b){cout a和b不相等 endl;}else{cout a和b相等 endl; // a和b相等}
}int main() {test01();return 0;
}
函数调用运算符重载 函数调用运算符 () 也可以重载由于重载后使用的方式非常像函数的调用因此称为仿函数仿函数没有固定写法非常灵活 class MyPrint
{
public:void operator()(string text) // 函数调用运算符重载函数注意是在 operator后加 ()当前是打印值{cout text endl;}};
void test01()
{//重载的操作符 也称为仿函数MyPrint myFunc;myFunc(hello world); // hello world
}class MyAdd
{
public:int operator()(int v1, int v2) // 函数调用运算符重载函数当前是返回值{return v1 v2;}
};void test02()
{MyAdd add;int ret add(10, 10);cout ret ret endl; // 20// 匿名对象调用 MyAdd()是匿名对象执行完当前行就会销毁MyAdd()(100, 100)是匿名对象调用重载函数cout MyAdd()(100,100) MyAdd()(100, 100) endl;
}int main() {test01();test02();return 0;
}
总结
需要注意的是虽然运算符重载提供了强大的功能但滥用它可能会导致代码难以理解和维护。因此对于每个运算符都需要仔细考虑是否有必要进行重载以及如何遵循最佳的代码设计和风格约定。