您的位置:首页 > 编程语言 > C语言/C++

C++学习笔记之面向对象基础

2019-04-07 10:10 330 查看

面向对象基础

如何理解OOP:
说到OOP就不能不说类了,类实际上是对一个实体的抽象化描述,而一个实体包含有属性和行为两种性质,所以类就从这两种性质来描述一个实体;通过将实体的属性转换为成员变量,把行为转换为成员方法;通过类实例化的每一个对象都有自己的独立的成员变量,而共享一套成员方法。这就像每一个人都是不一样的,都是独立的个体,而每个人可能会做同一件事情。而才C++中,通过一个this指针来区别不同对象调用的同一个方法,这个this指针是成员方法的第一个参数,只是没有显式的表现出来。

什么是this指针:
因为在面向对象语言中,每个对象拥有独立的成员变量,而共享一套成员方法,为了能够表明是哪个对象调用的方法,与其他对象区别,这时就需要一个指针来指向这个对象。当一个对象调用一个成员方法的时候,就将这个指针指向这个对象然后作为实参传给成员方法,这时成员方法就需要一个指针变量来接受这个指针,这个指针变量就是this指针,没有显式的表现出来,但它实质上是成员方法的第一个参数。在这里this指针具有常性,不能被修改。

delete 和 free的区别
1、因为C++中有对象,一个对象可能会使用除了本身之外的资源,就是再使用new在堆申请的资源,所以delete不能像free那样单单释放对象,delete会调用对象的析构函数,利用析构函数释放对象申请的外部资源,在调用free来释放对象,单纯的使用free会导致外部资源的泄露;因此delete会做两件事:调用对象的析构函数,调用free。
2、在堆上申请的内存,在函数结束时是自动不会调用析构函数的,必须手动释放,这就需要使用delete来调用对象的析构函数,delete是和new配对使用的,new了多少就要delete多少。
3、如果一个指针指向的是一个对象数组,如果只是使用delete不加上[],会释放该指针在堆上的所有内存,以及这个数组对象的第一个元素的外部资源(调用首元素会调用析构函数),而其他的对象的外部资源没有释放(其他对象不会调用析构函数),所以必须使用delete[]来释放一个指向一个数组的指针。

构造函数的初始化列表
1、规定了成员变量的初始化方式,但没有规定成员变量的初始化顺序,初始化顺序是和定义的顺序有关。初始化列表里做的事就是初始化。
2、如果成员变量中包含有const修饰的常量和引用的话,就必须使用初始化列表来进行初始化,要注意该对象类型的赋值和拷贝构造的操作,防止引用和const常量作为左值。

构造函数和析构函数
1.函数名字和类名相同
2.函数没有返回值
3.析构函数不能带参数,只能由一个析构函数
4.构造函数可以带任意参数,所以构造函数可以重载
5、每一个对象的定义都是分两步进行:开辟空间,调用构造函数;生命周期结束都是:先调用析构函数,在释放内存

浅拷贝的危害:
如果一个对象占有外部资源,使用浅拷贝就是将外部资源的地址也进行拷贝,如果其中一个对象调用了析构函数,就释放了这块内存,那么另一个对象指向这块内存的指针就成了野指针,再调用析构函数时,delete就会释放一块已经释放的的内存,相当于delete使用了两遍,delete了一个野指针;如果没有占用外部资源就不会有问题,为保险起见,一般我们都要防止浅拷贝。

拷贝构造和赋值重载函数
1、拷贝构造函数注意点:
防止浅拷贝,
2、赋值重载函数注意点:
1)防止自赋值;
2)防止内存泄露,应该先释放自己之前占有的内存
3)防止浅拷贝,再申请一块内存,来拷贝数据;

对象的生命周期:
1、函数调用传对象,要用引用来接收
2、函数返回一个对象是,应该返回一个临时对象,而不是一个已定义过的对象。
3、接受返回对象的函数调用时,按初始化的方式来接收,不要按赋值的方式来接收。
4、一个类型的对象要转化为另一个类时,看另一个类中是否包含有该类型的构造函数。
不然会出现没有对应构造函数的错误;
5、如果用一个引用类型接受一个临时对象的话,这个临时对象执行完语句之后不会析构,因为这个引用就是这个临时对象的别名,也就是它的名字可以通过这个引用来找到这个对象。

Test t;
t=2;//相当于t=Test(20);如果Test类中有包含一个整型为参数的构造函数,将会产生一个临时对象赋值给t;如果没有,就会报错;

Test p=Test(2,3);
这类的初始化和Test p(2,3)没有区别,不会产生一个临时对象。
用一个临时对象来拷贝构造一个该类型的新对象时,该临时对象不会产生,会被优化。

Test &p=Test();//该临时对象不会析构

左值引用和右值引用
左值引用和右值引用在汇编的角度是一样的,
eg:
cosnt int &b=30;
int &&c=30;
汇编代码是一样的,都是生成一个临时变量,让引用指向临时变量的地址。

不过右值引用还有其他的用途:
在拷贝构造和赋值重载函数中,如果一个对象的生存周期即将到了,要不把它的对象的内容拷贝给另一个对象,且这个对象所占的内存十分的大,那么如果调用拷贝构造函数(自己已经进行了深拷贝)的话,消耗时间很多,不如直接进行浅拷贝,这就是右值引用的好处。使用右值引用重载一个拷贝构造函数就会调用这个重新写过的拷贝构造函数而不会再调用之前的拷贝构造函数。这个系统会自动的识别调用,程序员不需要自己来实现。

普通成员函数和static修饰的成员函数的区别:
static修饰:
1.属于类的作用域
2.调用依赖类名称作用域
3.能任意访问私有的其它static静态成员(因为static修饰的成员函数没有this指针,所以无法确定要调用那个对象的成员;又因为成员函数都会隐式传入调用对象的this指针,而static修饰的成员函数没有this指针。因此它只能访问静态成员,和静态成员方法)
普通成员函数:
1.属于类的作用域(C 全局和局部{} C++ 多了个类作用域)
2.调用必须依赖于一个对象
3.能任意访问私有的其它成员

const修饰的成员函数
传入的是const 修饰的this指针,所以const修饰的成员函数不能调用普通的成员函数,但能够调用static修饰的成员函数,const放在函数的后面。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: