期末复习c++知识点大回顾,八篇文章让你永不破防(建议收藏)
Posted 行码棋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了期末复习c++知识点大回顾,八篇文章让你永不破防(建议收藏)相关的知识,希望对你有一定的参考价值。
目录总览
目录
五、运算符重载
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.常见运算符重载示例
+,- 运算符,以复数的运算为例:
#include<bits/stdc++.h>
using 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<<real<<" ";
if(imag!=0)
{
if(imag>0) cout<<"+ ";
cout<<imag<<"i\\n";
}
}
int main()
{
Complex t1(1,2);
Complex t2(2,3);
t2 = t1 + t2;//对象的赋值
t2.print();
return 0;
}
++ ,--重载
#include<bits/stdc++.h>
using 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<<num<<endl;
}
int main()
{
number n1(2);
n1++;
n1.print();
++n1;
n1.print();
return 0;
}
1、运算符前置自增运算符 , 用成员函数实现时,没有形式参数。
2、运算符后置自增运算符 ,另外增加一个形式上的形式参数,类型定为int。
这个参数只是用来区别两种自增算符,并不参加实际的运算。
<< 和>>运算符重载
#include<iostream>
using 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 <<"i\\n";
return out;
}
else
{
out << c.imag << "i\\n";
return out;
}
}
}
int main()
{
Complex cc;
cin>>cc;
cout<<cc;
return 0;
}
3.类型转换函数(类型转换运算符)
格式:
operator type(){
//具体代码
return data;
}
- type 是要转换的目标类型,data 是要返回的 type 类型的数据。
- 返回值data的类型和type目标类型必须是一样的。
既然已经知道了要返回 type 类型的数据,所以没有必要再像普通函数一样明确地给出返回值类型。 - 类型转换函数看起来没有返回值类型,其实是隐式地指明了返回值类型。
- 类型转换函数也没有参数,因为要将当前类的对象转换为其它类型,所以参数不言而喻。
#include <iostream>
using 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<<endl;
f = 12.5 + c1 + 6; //相当于 f = 12.5 + Complex::operator double(&c1) + 6;
cout<<"f = "<<f<<endl;
int n = Complex(43.2, 9.3); //先转换为 double,再转换为 int
cout<<"n = "<<n<<endl;
return 0;
}
运行结果:
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 是同级关系,没有谁的优先级是更高的。
也欢迎大家关注我的同名公众号获取更多信息和资料呀(^U^),欢迎大家在留言区交流。
以上是关于期末复习c++知识点大回顾,八篇文章让你永不破防(建议收藏)的主要内容,如果未能解决你的问题,请参考以下文章
期末复习c++知识点大回顾,八篇文章让你永不破防(建议收藏)
期末复习c++知识点大回顾,八篇文章让你永不破防(建议收藏)
期末复习c++知识点大回顾,八篇文章让你永不破防(建议收藏)