c++三大特性:封装、继承、多态
封装:把一类事物的属性和行为用类这种自定义的数据类型包起来,把需要隐藏的隐藏起来,把需要暴露的暴露出来,这就叫封装
类:描述一类事物的属性和行为的自定义的数据类型
c和c++中结构体的区别:c结构体中不能有函数,c++中结构体中可以有函数
c中空结构体内存大小为0,c++中空结构体内存大小为1
c++中结构体和类的区别:访问限定符不同,结构体的默认访问限定符为public,而类的默认访问限定符为private
访问限定符:public修饰的成员既可以在类内被访问,也可以在类外被访问
private和protected修饰的成员只能在类内被访问
对象:用类这种自定义的数据类型定义的变量叫对象
类的数据类型(定义数据类型系统不会分配空间)是抽象的,对象是具体的实体(定义变量会分配空间),用类的数据类型定义变量的过程叫实例化对象
this指针:this指针是一个隐含于每一个非静态成员函数中的特殊指针,它指向调用成员函数的那个对象,谁正在调用成员函数,谁就是当前类对象,this指针就指向谁
当一个对象调用成员函数时,编译程序现将对象的地址赋给this指针,然后调用成员函数,每次成员函数存取数据时都隐式使用this指针。this指针在成员函数的开始执行前构造,在成员的执行结束后清除
构造函数和析构函数
构造函数:构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,保证每个数据成员都有合适的初值,并且在对象的生命周期内只调用一次。(给成员变量初始化的)
构造函数特性:
函数名与类名相同
无返回值
编译器自动调用
参数不限制(构造函数可以有多个,可以重载)
构造函数不能为虚函数:调用构造函数后,才能生成一个对象,假设构造函数是虚函数,虚函数存在于虚函数表中,而去找虚函数表又需要虚函数表指针,而虚函数表指针又存在于对象中,所以矛盾在于:都没有对象,哪来的虚函数表指针呢?
谁调用的:系统自动调用的
什么时候调用的:实例化对象时
也就是:对象有了,这个函数也执行完了
没有自定义构造函数时,系统会提供一个无参函数体啥都没写的构造函数,一旦自己定义了构造函数,系统就不提供了
析构函数:与构造函数对应,当一个对象生命周期结束的时候,系统会自动调用析构函数,如果没有定义,系统提供,如果定义了,系统就不提供了
析构函数特性:
函数名是~类名
无参无返回值
只能有一个,不可以重载
析构函数可以是虚函数
作用:回收资源,比如构造函数在堆区申请空间,在析构函数里去释放
拷贝构造函数:拷贝构造函数是构造函数的一种,也称为复制构造函数,只有一个参数,参数类型是该类的引用
作用:使用类中已经创建好的对象来初始化新创建的对象,没定义时由系统自动提供(默认拷贝构造函数)
调用时机:
用类的一个对象去初始化另一个对象时
当函数的形参是类的对象时
当函数的返回值是类的对象或者引用时
深拷贝和浅拷贝:
一般情况下,当类中成员有指针变量、类中有动态内存分配时,常常需要用户自己定义拷贝构造函数。当出现类的等号赋值时,会调用拷贝函数,在未定义显示拷贝构造函数的情况下,系统会调用默认的拷贝函数——即浅拷贝,它能够完成成员的对应复制。
但当数据成员中有指针时,如果采用简单的浅拷贝,则两类中的两个指针将指向同一个地址,当对象快结束时,会调用两次析构函数,而导致指针悬挂现象。所以,这时,必须采用深拷贝。 深拷贝与浅拷贝的区别就在于深拷贝会在堆内存中另外申请空间来储存数据,从而也就解决了指针悬挂的问题。
简而言之,当数据成员中有指针时,必须要用深拷贝。