内容预览
运算符重载**
友元函数
一元运算符重载
重载 << 运算符*
正文
运算符重载(operator overloading)
-
运算符重载 :就是“想法转换”,简化函数调用的方式
把标准的函数使用方式,重新定义为自己认为的方式
运算符重载就是赋予运算符新的含义,同一个运算符可以有不同的功能 例如: +号可以对不同类型int, float等数据进行加法操作 << 既是位移运算符,又可以配合cout向控制台输出数据 C++本身已经对这些运算符进行了重载
-
demon
定义一个运算符重载就像定义一个函数,函数名称已oprator关键字开头
class Integer { public: Integer(): m_num(0){} Integer(int num): m_num(num){} const Integer operator+(const Integer & other) const { cout << "重载了运算符+,以便实现两个整型对象相加" << endl; return Integer(this->m_num + other.m_num); } private: int m_num; }; 主程序 Integer num1(1024); Integer num2(24); Integer num3 = num1 + num2;
注意:
1.运算符重载的语法格式:
返回类型 operator 被重载的运算符(参数列表)
2.编译器实际调用:
num3 = num1.operator+(num2);3.上图3个const:
1.第一个const修饰函数返回值,使用const传递引用,提高效率 2.第二个const修饰函数参数,参数在函数体内部不能改变 3.第三个const修饰函数,不改变成员变量
-
运算符重载列表
友元函数 -
友元函数
运算符声明成类成员函数还是独立友元函数,建议准测:
1.C++规定,赋值运算符=、数组下标运算符[ ]、函数调用运算符()、成员访问运算符->在重载时必须声明为类的成员函数 2.流运算符<<、>>、类型转换运算符不能定义为类的成员函数,只能是友元函数 3.一元运算符和复合赋值运算符重载时,一般声明类的成员函数 4.二元运算符在运算符重载时,一般声明为友元函数
-
应用场景
注意:1.对于很多运算符来说,可以使用成员函数或非成员函数来实现运算符重载; 一般来说,非成员函数应该是友元函数,这样才能直接访问类的私有数据。 2.在定义运算符时,必须选择其中的一种格式,而不能同时选择这两种格式; 同时定义这两种格式将被视为二义性错误,导致编译错误。 3.那么哪种格式最好呢? 对于某些运算符来说,成员函数是唯一合法的解释。其他情况下,这两种格式没有太大的区别。 根据类的设计,使用非成员函数版本可能更好(尤其是为类定义类型转换时)
赋值构造函数
-
自定义string(字符串)类,以简化字符串的操作
class String { public: String(char * str); friend ostream & operator<<(ostream & out, const String & str); String & operator=(String & str); virtual ~String(); private: int length; //字符串的实际长度(不包括\0) char * value; //实际存储字符的字符数组 }; 主程序 String str1 = "爱吃酸辣土豆丝"; String str2; str2 = str1;
注意: 如果我们不重载赋值运算符,对象str1的内容直接复制到新对象str2中。 对于没有指针的简单类来说这足够了。 但当我们拥有作为数据成员的指针时,逐字节的复制将会把指针从一个对象复制给另一个对象,而两个指针就会同时指向一个内存。
-
解决方案:
重载赋值运算符String & String::operator=(String & str) { delete[] value; //首先释放字符串的默认空间 length = strlen(str.value); //重新测量字符串长度 value = new char[length + 1]; strcpy(value, str.value); return *this; }
注意: 1.当重载赋值运算符时,务必确定将一个对象中的所有数据成员复制到另一个对象中 2.如果包含多个数据成员,则每个成员都需要复制到目标对象中
-
另一种状况
复制、拷贝构造函数
对于简单的类: 默认拷贝构造函数一般是够用的,没有必要再显式地定义一个功能类似的拷贝构造函数 当类拥有其他资源时: 如动态分配的内存 、打开的文件、指向其他数据的指针、网络连接等, 默认拷贝构造函数就不能拷贝这些资源,必须显式定义拷贝构造函数,以完整地拷贝对象的所有数据
应用场景
在下面三种场景中会调用复制构造函数:
1.当类的对象被初始化为同一类的另一个对象时
2.当对象被作为参数传递给一个函数时
3.当函数返回一个对象时