IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++知识总结(二) -> 正文阅读

[C++知识库]C++知识总结(二)

析构函数

class CLA_NAME{
	访问控制属性:
		//constructor 构造函数   函数名和类名相同 没返回值 也不能为void 可以重载
		//实例化对象时自动调用构造函数  new  作为类类型成员
		CLA_NAME(形参列表):INIT_LIST{
			
		}
		//析构函数   denconstructor  
		//当一个对象消亡(消失,离开了生命周期) 会 自动调用析构函数
		~CLA_NAME(void){
			
		}
	};
	1.在C++中,任何一个类中都有唯一的一个析构函数
	2.如果程序员没有手动实现析构函数,那么编译器将自动生成析构函数
	3.析构函数形如:
		~类名(void){
			
		}
		析构函数名  ~类名 
		析构函数没有返回值   也不是void
		析构函数没有参数   所以不能重载
		在一个类中,析构有且只有一个
		一般来说,析构函数用编译器自动生成的即可,但如果需要手动释放内存,则需要自行添加
	4.析构函数的调用顺序和构造函数严格相反
		构造函数的执行顺序: 
		父类(按继承顺序)的构造函数-->类类型成员(按定义的顺序)的构造函数-->本类的构造函数
		析构函数的执行顺序:
		本类的析构函数-->类类型成员的析构函数(按定义顺序的逆序)-->父类的析构函数(按继承的逆序)
	5.对象消亡时,自动调用析构函数
	  delete释放 new的对象时,调用析构函数
	
	6.析构函数的功能
		(1)释放动态内存    比如在构造函数时 new malloc 内存
		(2)关闭文件  fclose()   close()
		(3)删除临时文件    
		(4)释放资源

拷贝构造函数

特殊的构造函数
	如果一个类没有添加拷贝构造函数,那么编译器将自动生成一个拷贝构造函数,实现是浅拷贝
	如果一个类需要实现深拷贝,则需要自己添加拷贝构造函数
	拷贝构造函数形如:
	class CLA_NAME{
		CLA_NAME(const CLA_NAME& otherobj){//形参的const和&(引用)都不能省
			
		}
	};
		拷贝构造函数没有返回值  也不是void
		拷贝构造函数名字和类名相同
		拷贝构造函数的形参只有一个  同类型的  引用对象   必须是引用
	拷贝构造函数什么时候调用:
		当用一个已经存在的对象去实例化一个同类型的对象时,调用的是拷贝构造函数
	
	浅拷贝和深拷贝:
		浅拷贝就是按字节拷贝,即对象中的成员属性进行按字节复制,
			如果对象中有指针成员,就是把指针的值进行了拷贝(拷贝之后,两个指针指向同一块内存)
		深拷贝就是拷贝指针所指向的内容,而不是拷贝指针变量本身的值
	
	默认的拷贝构造函数:
		依次调用父类类型的拷贝构造函数(按继承顺序)
		依次调用类类型成员的拷贝构造函数(按成员定义顺序)
		本类类型的拷贝构造函数
	
	如果自己实现拷贝构造函数需要注意的问题:
		(1)需要实现父类成员的拷贝  在初始化列表中调用父类的拷贝构造函数  
				如果在初始化列表中没有调用父类的拷贝构造,则默认调用无参构造
		(2)需要实现类类型成员的拷贝 在初始化列表中调用类类型成员的拷贝构造函数
				如果在初始化列表中没有调用类类型成员的拷贝构造,则默认调用无参构造
		(3)需要实现本类中其它成员的拷贝 

拷贝复制函数

当存在的两个同类型的变量进行赋值操作时,会调用拷贝赋值函数 
	如果一个类没有实现拷贝赋值函数,则编译器会自动生成一个拷贝赋值函数,默认实现是浅拷贝赋值
	如果需要实现深拷贝赋值,则需要手动实现
	拷贝赋值函数形如:
	class CLA_NAME{
		//拷贝赋值函数
		CLA_NAME& operator=(const CLA_NAME& otherobj){
			
		}
	};
	obj1 = obj2;  //拷贝赋值
	obj1.operator=(obj2); //拷贝赋值
	
	默认的拷贝赋值函数:
		1.依次调用父类的拷贝赋值函数   按继承顺序 
		2.依次调用类类型成员的拷贝赋值函数  按声明定义顺序
		3.本类的拷贝赋值函数
	
	如果自己实现拷贝赋值函数需要注意:
		1.需要拷贝父类的成员 
		2.需要拷贝类类型成员
		3.其它成员的拷贝
			无先后顺序,先写先执行

	编译器自动生成无参构造和拷贝构造
	如果手动提供无参构造,编译器自动生成拷贝构造
	如果手动提供拷贝构造,编译器不再生成无参构造

要能够区分:什么时候调用拷贝构造 什么时候调用拷贝赋值
	拷贝构造: 有新对象  用存在的对象构造一个新的对象  普通参数传递(没有引用)拷贝构造
	拷贝赋值:对象都已存在 对象之间进行赋值操作
默认的拷贝构造和拷贝构造都是浅拷贝
	什么是浅拷贝,什么是深拷贝?
		浅拷贝按字节拷贝 只拷贝成员本身的内容,如果成员是指针,则拷贝指针本身,一个地址,指针所指向的内容共享
		深拷贝对于普通成员也是按字节拷贝  如果成员是指针,则拷贝指针所指向的内容

友元

在一个类中可以声明全局函数为该类的友元函数,
		在友元函数中,可以通过对象访问该类的所有的属性和方法
	在一个类中可以声明其它类为该类的友元类
		那么,在友元类中,可以通过对象访问该类的所有的属性和方法
	class CLA_NAME{
		
		
		friend RET_TYPE FUNC_NAME(ARGLIST,...);
		friend class OTHER_CLASS_NAME;
	};

运算符重载

运算符分类:
		1.单目运算符
			+(正号) -(负号)  &(取地址)  *(取值)   !(取反)  ~(按位取反)
			++  --
		
		2.双目运算符
			+ - * / %  &&  ||  & |  ^  >>  <<   []
		3.三目运算符
			?:   不能重载
		4.  ()  操作数个数不确定
	成员方式重载
		#obj     obj.operator#()
		M#N      M.operator#(N)
	友元方式重载(全局函数的重载形式)
		#obj     operator#(obj)
		M#N      operator#(M,N)
		<<  >> 只能以友元方式重载
		cout.operator<<(obj);     operator<<(cout,obj)
		cin.operator>>(obj);      operator>>(cout,obj)
	friend ostream& operator<<(ostream& os,const CLA_NAME& obj);
	//cout  ostream类的象
	friend istream& operator>>(istream& is,CLA_NAME& obj);

	单目运算符以成员方式重载,该函数无参数;
	单目运算符以友员方式重载,该函数有一个参数
	双目运算符以成员方式重载,该函数有一个参数
	双目运算符以友员方式重载,该函数有两个参数

	双目运算符:
		1.+ - * /
			左右操作数不会改变
			表达式的结果是右值   所以返回值没有引用
		2.+= -= *= /=  = 
			左操作数发生改变    右操作数不变
			表达式的结果是左值   返回左操作数的引用
		3. >> / <<
			只能以友元方式(全局函数)重载
			左操作数 ostream/istream类型  不能是常量,不能拷贝(参数和返回值都是引用)
			ostream& operator<<(ostream& os,const CLS& obj);
			istream& operator>>(istream& is,CLS& obj);
			表达式的结果是左操作数的引用 cout/cin     支持连用 cout << a << b << endl;

	单目运算符
		1. -(取负) !(取反) ~(按位取反)
		   操作数不会改变
		   表达式的结果是右值
		2. ++ --++--
				操作数发生改变
				表达式的结果是自增减之后的值
				表达式的结果是左值  返回操作数的引用
			后++--
				操作数发生改变
				表达式的结果是原来的值 
				表达式的结果是右值  返回操作数原来的值
	下标运算符:
		obj[index]
		双目运算符,左操作数是一个具有容器特性(String)的对象
		右操作数是容器中特定位置的数据元素的索引(基零的下标)
		下标运算符的结果可以是左值,也可以是右值,由对象的常属性决定
			常对象返回的是右值   普通对象返回的是左值
		一般来说,[]运算符会实现两个版本的
	
	
	比较运算符  关系运算符:
	==  !=  <   >   <=  >= 
		==  !=   a==b((a<b||a>b) == false)  
	
		注意:如果把类类型对象存储于容器中,一般都需要重载<==!=
		如果重载==,也有必要重载!=
	
	重载()运算符    -----   函数对象
		如果一个类重载了()运算符,那么该类的对象可以称为 函数对象  
		重载的()运算符,返回值类型可以视情况而定  是否引用也可以视情况而定
		重载的()运算符函数参数可以任意
		在C++,重载()运算符非常有用,取代了C语言中的函数指针
		重载()运算符类的对象  仿函数  函数对象
		
	& 取地址运算符    
		编译器自动生成两个&运算符函数  返回对象的地址
		形式:
		class CLA_NAME{
			
			CLA_NAME *operator&(void){
				return this;
			}
			const CLA_NAME* operator&(void)const{
				return this;
			}
		};
		C++11之前的版本中,如果有一个空类(啥也没写),至少有6个函数
			无参构造  拷贝构造  拷贝赋值  析构函数   取址函数(2const版本和非const版本)
		C++11之前一个类中最少会有几个函数? 5个
			手动实现一个拷贝构造函数  无参构造将不会自动生成
		C++11版本会自动再添加两个函数:
			移动拷贝构造函数
			移动拷贝赋值函数
	
	重载位运算符
		&  |  ~  ^  >>  <<  
		
	重载解引用(*)以及间接解引用(->)
		
		
	成员指针   
		.*  直接成员指针解引用  不能重载
		->* 间接成员指针解引用  能够重载
	
	重载类型运算符:
	class A{
	public:
		A(const B& b){}//B类型对象--->A类型对象
		operator B(void)const{//在A类中重载B类型运算符  A类型对象-->B类型对象

		}
	};
	
	重载new/delete运算符
		在类里用静态方法
		class A{
			static void *operator new(size_t size){
				return malloc(size);
			}
			static void *operator new[](size_t size){
				return malloc(size)}
			static void operator delete(void *ptr){
				free(ptr);
			}
			static void operator delete[](void *ptr){
				free(ptr);
			}
		};
		用全局方式实现
		void *operator new(size_t size){
			return malloc(size);
		}
		void *operator new[](size_t size){
			return malloc(size)}
		void operator delete(void *ptr){
			free(ptr);
		}
		void operator delete[](void *ptr){
			free(ptr);
		}
	实例化对象:
		分配内存 --->  调用构造函数
	对象消亡:
		调用析构函数 --->  回收内存

继承

在继承的语法中,被继承的类称为父类,基类,继承父类的这个类称为子类或者派生类
	
	继承的意义:
		子类拥有父类的属性和方法  子类可以定义自己的属性和方法
		代码的复用    功能的扩展
	
#继承方式:
		私有继承  private    默认的
		保护继承  protected
		公开继承  public
		
	继承方式所表达的含义是 从父类中继承到子类中的属性将是怎样的访问控制属性
	1.访问控制属性
	关键字        属性    基类  子类   外部   友元
	public       公有     OK    OK    OK     OK
	protected    保护     OK    OK    NO     OK
	private      私有     OK    NO    NO     OK
	2.继承方式对基类中继承下来的成员变量的访问控制属性的影响
		基类中不同访问控制属性的变量 通过不同的继承方式 到达子类的变成的访问控制 属性
	基类     public公开继承       protected保护继承     private私有继承
	公有        公有                 保护                 私有
	保护        保护                 保护                 私有
	私有        私有(不能访问)        私有(不能访问)       私有(不能访问)
		
	基类中的私有属性不管通过什么继承方式,到达子类都不能访问
	
	通过继承,在基类中定义的任何成员,也都成为了子类的成员。
		但是基类中的私有成员,子类虽然拥有但却不能访问
		基类中的保护成员和公开成员,在子类中是直接可以访问的
	公开继承:
		基类中保护的成员,通过公开继承方式,在子类中依然是保护的成员
		基类中公司的成员,通过公开继承方式,在子类中依然是公开的成员
		在使用时基本使用公开继承 
	保护继承:
		基类中保护的、公开的成员,通过保护继承到子类变成子类中保护的成员
	私有继承:
		基类中保护的、公开的成员,通过私有继承到子类变成子类中私有的成员
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-14 13:08:38  更:2021-09-14 13:10:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 23:19:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码