目录总览
c++知识点复习最全整理(一)
c++知识点复习最全整理(二)
c++知识点复习最全整理(三)
c++知识点复习最全整理(四)
c++知识点复习最全整理(五)
c++知识点复习最全整理(六)
c++知识点复习最全整理(七)
c++知识点复习最全整理(八)
目录
五、运算符重载
1.运算符new,delete介绍
1.1.new申请空间
1.2.delete释放空间
2.运算符重载
2.1.相关问题
2.2.常见运算符重载示例
五、运算符重载
1.运算符new,delete介绍
1.1.new申请空间
形式:
指针变量 = new<数据类型>[长度]
- 申请一个整型(int)空间
int *ptr; ptr = new int;
- 申请一个整型空间并且初始化
int *ptr; ptr = new int(5);
- 申请长度为20的一维数组,但不能进行初始化
int *p; p = new int[10];
注意:
- 当分配的长度为1个单位时,可以省略方括号里面的整数。
int *int_ptr = new int; //等价形式 int *int_p = new int[1];
- 使用new分配空间时,方括号里面的数值可以是常量,也可以是变量。还可以是数值表达式。
int size = 10; //常量 int *np = new int[5]; //变量 int *np1 = new int[size]; //表达式 int *np2 = new int[size+10];
- 使用new分配的空间是连续的,可以使用指针访问分配空间里面的每一个元素。
int *p = new int[20]; //将第11个元素赋值为100 p[10] = 100; //或者 *(p+10) = 100;
- 如果当前存储器无法分配更多的内存空间,new运算符返回值为0(NULL)
1.2.delete释放空间
delete释放空间只有两种形式:
//1 delete p; //2 delete []p;
delete 释放new分配的单个对象指针指向的内存
delete[] 释放new分配的对象数组指针指向的内存
其实两种方式区别不大,主要区分在类中体现。
1.针对简单类型(int,float,long,double,char,struct等)
使用new分配后的无论是数组还是非数组形式内存空间用两种方式均可
如:
int *a = new int[10]; delete a; //或delete [] a;
此种情况中的释放效果相同 原因在于分配简单类型内存时,内存大小已经确定,系统可以记忆并且进行管理,在析构时,系统并不会调用析构函数,
2.对于类class来说,两种方式体现出差异。
A *a = new A[10]; delete a; //仅释放了a指针指向的全部内存空间 但是只调用了a[0]对象的析构函数 剩下的从a[1]到a[9]这9个用户对应内存空间将不能释放从而造成内存泄漏 delete [] a; //释放了a指针指向的全部内存空间 并且调用使用类对象的析构函数释放用户自己分配的内存空间
注意:
①用new运算符获得的内存空间,只许使用一次delete,不允许多次对同一块空间进行多次释放,否则将会产生严重错误。
②delete只能用来释放由new运算符分配的动态内存空间,对于程序中的变量、数组的存储空间,不得使用delete运算符去释放。
2.运算符重载
运算符重载是通过定义函数实现的,即定义一个重载运算符的函数,在需要执行被重载的运算符时,系统自动调用该函数,以实现相应的运算。
运算符重载实质上是函数的重载。
重载形式:
函数类型 operator 运算符名称 (形参表列) { 对运算符的重载处理 }
2.1.相关问题
- 运算符能否进行重载
可以重载的运算符
+ - * / % ^ & | ~ ! = < > += -= *= /= % ^= &= |= << >> >>= <<= == != <= >= && || ++ -- ->* ‘ -> [] () new delete new[] delete[]
不能重载的运算符
| Operator | Name |
| . | 类属关系运算符 |
| .* | 成员指针运算符 |
| :: | 作用域运算符 |
| ? : | 条件运算符 |
| # | 编译预处理符号 |
| sizeof() | 取数据类型的长度 |
- 运算符重载不能创造新的运算符号,例如不能创建@@表示幂运算
- 重载的运算符保持运算符的一些性质不变(优先级,结合性,操作个数,语法结构)
- 赋值运算符(=)和地址运算符(&)不需要重载
运算符重载函数一般采用两种方式:
- 成员函数的形式
- 友元函数的形式
运算符函数是一种特殊的成员函数或友员函数(全局函数通常被指定为友元函数)
2.2.常见运算符重载示例
+,- 运算符,以复数的运算为例:
#includeusing namespace std; class Complex { private: double real,imag;//实部和虚部 public: Complex(double r=0,double i=0):real(i),imag(i){}//构造函数 Complex operator +(const Complex &a);//重载+运算符 Complex operator -(const Complex &a);//重载-运算符 void print(); }; //定义为成员函数,可以访问类内的私有变量 Complex Complex::operator +(const Complex&a) { Complex temp(real+a.real,imag+a.imag); return temp; } Complex Complex::operator -(const Complex&a) { Complex temp(real-a.real,imag-a.imag); return temp; } void Complex::print() { cout< 0) cout<<"+ "; cout< ++ ,--重载
#includeusing namespace std; class number { private: int num; public: number(int n=0):num(n){}; number& operator++();//前置自增 number operator++(int);//后置自增 void print(); }; number& number::operator++() { num++; return *this;//前置自增要保证先增加,然后返回增加后的数据,所以返回类型是引用类型 } number number::operator++(int)//int为形式参数,不参与实际运算 { number temp(*this);//保存临时的变量 num++;//自增1 return temp;//返回之前保存的没有进行加自增的变量 } void number::print() { cout< 1、运算符前置自增运算符 , 用成员函数实现时,没有形式参数。
2、运算符后置自增运算符 ,另外增加一个形式上的形式参数,类型定为int。
这个参数只是用来区别两种自增算符,并不参加实际的运算。
<< 和>>运算符重载
#includeusing namespace std; class Complex { private: double real,imag; public: Complex(double r=0,double i=0):real(r),imag(i){} friend istream& operator >> (istream& in,Complex &c); friend ostream& operator << (ostream& out,Complex c); }; istream& operator >> (istream& in,Complex &c) { cout<<"请输入实部和虚部n"; in >> c.real >> c.imag; return in; } ostream& operator << (ostream& out,Complex c) { if(c.real!=0) { out << c.real ;//实部输出 if(c.imag==0) { out << 0 << 'n'; return out; } else if(c.imag>0) { out << "+" << c.imag <<"in"; return out; } else { out << c.imag << "in"; return out; } } } int main() { Complex cc; cin>>cc; cout< 3.类型转换函数(类型转换运算符) 格式:
operator type(){ //具体代码 return data; }
- type 是要转换的目标类型,data 是要返回的 type 类型的数据。
- 返回值data的类型和type目标类型必须是一样的。
既然已经知道了要返回 type 类型的数据,所以没有必要再像普通函数一样明确地给出返回值类型。- 类型转换函数看起来没有返回值类型,其实是隐式地指明了返回值类型。
- 类型转换函数也没有参数,因为要将当前类的对象转换为其它类型,所以参数不言而喻。
#includeusing namespace std; class Complex { public: Complex(): real(0.0), imag(0.0){ } Complex(double real, double imag): real(real), imag(imag){ } public: friend ostream & operator<<(ostream &out, Complex &c); //实现两个复数的相加 friend Complex operator+(const Complex &c1, const Complex &c2); operator double() const { return real; } //类型转换函数 private: double real; //实部 double imag; //虚部 }; //重载>>运算符 ostream & operator<<(ostream &out, Complex &c) { out << c.real <<" + "<< c.imag <<"i";; return out; } //重载+运算符 Complex operator+(const Complex &c1, const Complex &c2) { Complex c; c.real = c1.real + c2.real; c.imag = c1.imag + c2.imag; return c; } int main() { Complex c1(24.6, 100); double f = c1; //相当于 double f = Complex::operator double(&c1); cout<<"f = "< 运行结果:
f = 24.6 f = 43.1 n = 43注意:
- type 可以是内置类型、类类型以及由 typedef 定义的类型别名,任何可作为函数返回类型的类型(void 除外)都能够被支持。一般而言,不允许转换为数组或函数类型,转换为指针类型或引用类型是可以的。
- 类型转换函数一般不会更改被转换的对象,所以通常被定义为 const 成员。
- 类型转换函数可以被继承,可以是虚函数。
- 一个类虽然可以有多个类型转换函数(类似于函数重载),但是如果多个类型转换函数要转换的目标类型本身又可以相互转换(类型相近),那有时候就会产生二义性。例如:
operator double() const { return m_real; } //转换为double类型 operator int() const { return (int)m_real; } //转换为int类型那么下面的代码就会出错:
Complex c(12.2, 30); float f = 1.1 + c;编译器可以调用 operator double() 将 c 转换为 double 类型,也可以调用 operator int() 将 c 转换为 int 类型,两种数据类型都可以和 1.1 进行加法运算。而且从 Complex 转换为 double 与从 Complex 转化为 int 是同级关系,没有谁的优先级是更高的。



