盐城市滨海县建设局网站,网络营销广告案例,域名大全免费网站,平面磨床东莞网站建设重载操作符C允许我们重新定义操作符#xff08;例如#xff1a;#xff0c;-#xff0c;*#xff0c;/#xff09;等#xff0c;使其对于我们自定义的类类型对象#xff0c;也能像内置数据类型#xff08;例如#xff1a;int#xff0c;float#xff0c;double允许我们重新定义操作符例如-*/等使其对于我们自定义的类类型对象也能像内置数据类型例如intfloatdouble等一样直观可以进行加减乘除比较大小等等操作。重载操作符本质是函数只是这个函数的函数名比较特别为operator后接需要重新定义的操作符的符号。例如重载号函数名为operator重载-号函数名operator-。因为重载操作符本质是函数所以实际上就是为某个自定义的数据类类型或枚举类型实现函数重载比如内置int类型已经有int operator(int, int)版本我们有一个自定义的complex复数类要想跟内置的int类型有一样直观的操作两个复数相加只要我们为自定义的complex复数类重定义操作符提供complex operator(complex, complex)版本即可。重载操作符语法返回值类型 operator操作符号(形参列表)
{
}重载操作符的两种形式对于大多数重载操作符来说可以定义为全局函数或类的成员函数。1.重载操作符为全局函数并且通常必须将这个全局函数设置为所操作类的友元#include iostream
using namespace std;class MyInt
{friend MyInt operator(const MyInt a, const MyInt b); //这个函数为MyInt类的友元public:MyInt():m_num(0){}MyInt(const int num):m_num(num){}int getNum() const{return m_num;}private:int m_num;
};//重载操作符为全局函数
MyInt operator(const MyInt a, const MyInt b)
{MyInt temp;temp.m_num a.m_num b.m_num; //如果没有把这个全局函数设置为操作类MyInt的友元则不能直接访问MyInt类的//私有成员变量m_numreturn temp;
}int main(int argc, char *argv[])
{MyInt a(1);MyInt b(2);MyInt c a b; //本质是调用了全局函数即 MyInt c operator(a, b);MyInt d operator(a, b); cout a b c.getNum() endl;cout operator(a, b) d.getNum() endl;return 0;
}注意重载操作符为全局函数时本质是调用了该全局函数。例如MyInt c a b; //本质是调用了全局函数即 MyInt c operator(a, b);2.重载操作符为类的成员函数#include iostream
using namespace std;class MyInt
{public:MyInt():m_num(0){}MyInt(const int num):m_num(num){}int getNum() const{return m_num;}MyInt operator(const MyInt b) //重载操作符为类成员函数{MyInt temp;temp.m_num this-m_num b.m_num;return temp;}private:int m_num;
};int main(int argc, char *argv[])
{MyInt a(1);MyInt b(2);MyInt c a b; //本质是调用了MyInt类的成员函数即 MyInt c a.operator(b);MyInt d a.operator(b);cout a b c.getNum() endl;cout a.operator(b) d.getNum() endl;return 0;
}注意重载操作符为类的成员函数时本质是调用了该类的成员函数。例如MyInt c a b; //本质是调用了MyInt类的成员函数即 MyInt c a.operator(b);重载操作符为全局函数和重载操作符为类的成员函数的形参区别对于重载操作符为全局函数和重载操作符为类的成员函数形参的个数看上去是有区别的一般重载操作符为类的成员函数其形参个数比重载操作符为全局函数的形参个数少1个因为重载操作符为类的成员函数类中有一个隐含的this指针形参限定为重载操作符函数的第一个形参。重载操作符为全局函数还是重载操作符为类的成员函数应该怎么选择对于重载操作符可以为一个普通的全局函数或一个类的成员函数这两种方式来实现我的建议是对于能够使用类的成员函数来实现的我们应该选择用类的成员函数来实现因为选择用普通的全局函数来实现需要把这个全局函数设置为操作类的友元从而达到可以直接访问该操作类的非共有成员变量的目的但这破坏类的封装性。不能重载的操作符. :类的对象访问操作符
.* -* :类的对象或或类的对象指针访问类中的函数指针操作符
:: :域操作符
? :条件操作符
sizeof :长度操作符
# :预处理操作符 重载操作符可以给我们自定义的类类型对象的进行操作符运算的时候更加直观。但不要滥用重载操作符。1.不能改变内置类型的操作符的含义。例如int operator(int, int)2.不能为内置类型定义额外的新的操作符。例如不能定义两个数组为操作数的operator3.逗号,取地址逻辑与逻辑或||这些操作符具有有用的内置含义不建议重载。假设我们有一个MyInt类实现的功能跟内置的类型int一样。那么下面我们为这个MyInt类实现一下相关的操作符重载吧。重载输出操作符分析对于内置的类型int
int a 0;
cout a endl;操作符有两个操作数
第一个左操作数数据类型为ostream
第二个右操作数数据类型为const int
所以我们只能重载输出操作符为全局函数不能为MyInt类的成员函数
因为重载操作符为类的成员函数的第一个操作数数据类型限定为this指针
而我们需要的是第一个操作数数据类型为ostream
因为输出a后后面的操作是还能输出换行的所以返回值类型为ostream经过以上分析我们可以得出重载输出操作符的全局函数为ostream operator(ostream cout, const MyInt a)#include iostream
using namespace std;class MyInt
{friend ostream operator(ostream cout, const MyInt a);public:MyInt():m_num(0){}MyInt(const int num):m_num(num){}private:int m_num;
};ostream operator(ostream cout, const MyInt a)
{cout a.m_num;return cout;
}int main(int argc, char *argv[])
{MyInt a;cout a endl;return 0;
}重载输入操作符分析对于内置的类型int
int a 0;
int b 0;
cin a b;操作符有两个操作数
第一个左操作数数据类型为istream
第二个右操作数数据类型为const int
所以我们只能重载输出操作符为全局函数不能为MyInt类的成员函数
因为重载操作符为类的成员函数的第一个操作数数据类型限定为this指针
而我们需要的是第一个操作数数据类型为istream
因为输入a后后面的操作是还能输入b的所以返回值类型为istream经过以上分析我们可以得出重载输入操作符的全局函数为istream operator(istream cin, MyInt a)#include iostream
using namespace std;class MyInt
{friend ostream operator(ostream cout, const MyInt a);friend istream operator(istream cin, MyInt a);public:MyInt():m_num(0){}MyInt(const int num):m_num(num){}private:int m_num;
};ostream operator(ostream cout, const MyInt a)
{cout a.m_num;return cout;
}istream operator(istream cin, MyInt a)
{cin a.m_num;return cin;
}int main(int argc, char *argv[])
{MyInt a;MyInt b;cout 请输入a和b的值用空格隔开 endl;cin a b;cout a a b b endl;return 0;
}算术运算符和关系运算符一般来说我们应该将算术操作符和关系操作符定义为非成员函数。这是因为算术操作符和关系操作符中例如有左操作数为int a 1右操作数为double b 2.12345进行 a b运算时左操作数a会转成跟右操作数b的精度一样的double类型即a b 1.000000000000000双精度保留15位小数 2.123450000000000双精度保留15位小数如果将算术操作符和关系操作符定义定义为类的成员函数时左操作数限定为隐含的this指针就违背了在C/C中如果一个表达式中含有不同类型的常量或变量在计算时会将它们自动转换为精度更高的同一种数据类型。重载相加操作符1.返回值类型为MyInt因为两个数相加是不能改变左操作数或右操作数的值的所以返回值类型为MyInt而不是MyInt2.重载相加操作符的非成员函数为MyInt operator(const MyInt a, const MyInt b)#include iostream
using namespace std;class MyInt
{friend ostream operator(ostream cout, const MyInt a);friend istream operator(istream cin, MyInt a);friend MyInt operator(const MyInt a, const MyInt b);public:MyInt():m_num(0){}MyInt(const int num):m_num(num){}private:int m_num;
};ostream operator(ostream cout, const MyInt a)
{cout a.m_num;return cout;
}istream operator(istream cin, MyInt a)
{cin a.m_num;return cin;
}MyInt operator(const MyInt a, const MyInt b)
{return MyInt(a.m_num b.m_num);
}int main(int argc, char *argv[])
{MyInt a(1);MyInt b(2);cout a b a b endl;return 0;
}重载复合赋值操作符1.返回值类型为MyInt因为x y是要改变左操作数x并且返回的还是被修改后的x的2.重载复合赋值操作符的非成员函数为MyInt operator(MyInt a, const MyInt b)#include iostream
using namespace std;class MyInt
{friend ostream operator(ostream cout, const MyInt a);friend istream operator(istream cin, MyInt a);friend MyInt operator(MyInt a, const MyInt b);public:MyInt():m_num(0){}MyInt(const int num):m_num(num){}private:int m_num;
};ostream operator(ostream cout, const MyInt a)
{cout a.m_num;return cout;
}istream operator(istream cin, MyInt a)
{cin a.m_num;return cin;
}MyInt operator(MyInt a, const MyInt b)
{a.m_num b.m_num;return a;
}int main(int argc, char *argv[])
{MyInt a(1);MyInt b(2);a b;cout after a b, a a endl;return 0;
}重载相等操作符不等操作符-1.如果类中有一个操作是确认该类中的两个对象是否相等的我们应该将该函数名定义为operator而不是定义一个命名函数。因为我们更习惯于用操作符来比较两个对象是否相等。2.对于一个类如果我们定义了operator也应该定义operator!。3.定义了operator的类更容易与标准库一起使用。例如find默认使用了操作符如果定义了那么这么算法可以无须任何特殊处理而用于该类类型。#include iostream
using namespace std;class MyInt
{friend ostream operator(ostream cout, const MyInt a);friend istream operator(istream cin, MyInt a);friend bool operator(const MyInt a, const MyInt b);friend bool operator!(const MyInt a, const MyInt b);public:MyInt():m_num(0){}MyInt(const int num):m_num(num){}private:int m_num;
};ostream operator(ostream cout, const MyInt a)
{cout a.m_num;return cout;
}istream operator(istream cin, MyInt a)
{cin a.m_num;return cin;
}bool operator(const MyInt a, const MyInt b)
{return a.m_num b.m_num;
}bool operator!(const MyInt a, const MyInt b)
{return a.m_num ! b.m_num;
}int main(int argc, char *argv[])
{MyInt a(1);MyInt b(2);MyInt c(1);if (a b)cout a b endl;else cout a ! b endl;if (a c)cout a c endl;else cout a ! c endl;if (a ! b)cout a ! b endl;else cout a b endl;if (a ! c)cout a ! c endl;else cout a c endl;return 0;
}重载赋值操作符1.C是允许类类型对象给同类型的其他对象赋值的具体可查看我写的这篇文章里利用等号法创建对象的介绍C面向对象编程之二构造函数、拷贝构造函数、析构函数这里不再累赘。类赋值操作符形参的数据类型为该类类型通常形参为该类类型的const引用,或该类的非const引用或类类型或更多的其他数据类型例如MyInt类中那么该类的赋值操作符形参可为const MyInt 或MyInt 或MyInt。如果我们没有定义赋值操作符那么编译器将为该类提供一个。所以类赋值操作符必须是类成员函数以便编译器可以知道是否需要为该类提供一个。2.重载赋值操作符的返回值类型必须是*this的引用即左操作符的引用这样子返回是跟内置数据类型的赋值是一致的。因为赋值返回*this的引用这样子就不需要创建一个该类的一个临时对象然后将临时对象返回然后再调用该类的拷贝构造函数将该临时对象的值拷贝后又释放该临时对象这一系列的系统开销从而提高代码的执行效率。#include iostream
using namespace std;class MyInt
{friend ostream operator(ostream cout, const MyInt a);friend istream operator(istream cin, MyInt a);public:MyInt():m_num(0){}MyInt(const int num):m_num(num){}MyInt operator(const MyInt b){m_num b.m_num;return *this;}private:int m_num;
};ostream operator(ostream cout, const MyInt a)
{cout a.m_num;return cout;
}istream operator(istream cin, MyInt a)
{cin a.m_num;return cin;
}int main(int argc, char *argv[])
{MyInt a(1);MyInt b a;cout a a endl;cout b b endl;return 0;
}好了关于重载操作符篇幅比较长本文对重载操作符,,,,,!,进行了讲解还有一些比较重要的操作符比如前后前--后--下标操作符[]等还没有介绍就放到下一篇博文吧