一、面向对象基本内容
1.什么是面向对象编程
面向对象编程(Object-Oriented Programming , OOP)
面向对象编程的本质:以类的方式组织代码,以对象的组织(封装)数据
从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象。
从代码运行角度考虑是先有类后有对象。类是对象的模板。
2.面向对象与面向过程的区别
面向过程:
步骤清晰简单,第一步做什么,第二步做什么…
面对过程适合处理一些较为简单的问题
面向对象:
物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。
面向对象适合处理复杂的问题,适合处理需要多人协作的问题!
形象描述:(装修房子)
面向对象:粉刷、铺地、搬家具
面向过程:搬家具—>沙发,衣柜,洗衣机等等详细到每一个步骤
总结:
对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理
二、类与对象
类与对象的概念
类:类是对同一类对象的抽象总结,是一个概念。
对象:按照类的规定创建的实体。
1.类
类是描述对象的“基本原型”,它定义一类对象所能拥有的数据和能完成的操作。在面向对象的程序设计中,类是程序的基本单元。
相似的对象可以归并到同一个类中去,就像传统语言中的变量与类型关系一样。
程序中的对象是类的一个实例,是一个软件单元,它由一组结构化的数据和在其上的一组操作构成。
2.对象
可以将现实生活中的对象经过抽象,映射为程序中的对象。对象在程序中是通过一种抽象数据类型来描述的,这种抽象数据类型称为类(class)。
必须声明该类类型的一个变量,这个变量没有定义一个对象。实际上,它只是一个能够引用对象的简单变量。
该声明要创建一个对象的实际的物理拷贝,并把对于该对象的引用赋给该变量。
3.类与对象的关系
类(class)和对象(object)是两种以计算机为载体的计算机语言的合称。对象是对客观事物的抽象,类是对对象的抽象。类是一种抽象的数据类型。
类是Java的核心和本质。它是Java语言的基础,因为类定义了对象的本质。类定义了一种新的数据类型,可以用新类型来创建该类型的对象。
它们的关系是,对象是类的实例,类是对象的模板。对象是通过new classname产生的,用来调用类的方法;类的构造方法 。
类就是拥有相等功能和相同的属性的对象的集合 – 抽象的
对象就是类的实例 – 具体
类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物。(动物、植物、手机、电脑…)
Person类、Pat类、Car类等,这些类都是用来描述/定义某一类具体事物应该具备的特点和行为
对象是抽象概念的具体实例
张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例
能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念
三、实例化对象
类是一个抽象的概念,因此需要按照这个概念创建对应的对象实体,C++中有两种类型的对象:
● 栈内存对象
在生命周期结束(所在的花括号执行完)后,自动被销毁。
栈内存对象使用 . 调用成员。
● 堆内存对象
需要使用new关键字创建,使用delete关键字销毁,如果不销毁,则会持续存在,容易导致内存泄漏的问题,内存泄漏最终可能会导致程序卡顿,甚至卡死。
堆内存对象通常使用指针来保存堆内存对象的地址。
堆内存对象使用 -> 调用成员,在Qt Creator下,直接打.会转换成 ->
四、封装
面向对象的三个基本特征是:封装、继承、多态。其中,封装可以隐藏实现细节,使得代码模块化
什么是封装?
封装可以隐藏实现细节,使得代码模块化;封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。在面向对象编程上可理解为:把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
封装有利于提升程序的安全性。
五、构造函数
概念:
构造函数类内一种特殊的函数,用来创建一个对象。如果一个类中,程序员不手动编写构造函数,编译器会为这个类自动添加一个无参构造函数,且此函数的函数体为空;如果程序员手写了任意一个构造函数,编译器就不再自动添加构造函数了。
构造函数要求函数名必须与类名完全一致,且构造函数无需写返回值。
特性
虽然叫构造函数,但它的作用并不是构造一个对象(申请空间创建对象),而是初始化对象。
特征如下
函数名与类名相同;
无返回值;
对象实例化时编译器自动调用对应的构造函数;
构造函数可以重载;
如果编译器没有显式的定义构造函数,编译器会自动生成一个无参的默认构造函数,一旦我们显式定义,编译器就不再生成;
六、 析构函数
析构函数是与构造函数对立的函数。
构造函数 | 析构函数 |
手动调用 | 在对象被销毁时自动调用 |
通常用于在对象创建时初始化 | 通常用于在对象销毁时回收资源 |
可以被重载 | 不可以重载,因为没有参数 |
函数名是类名 | 函数名是~类名 |
七、作用域限定符 ::
名字空间
std是C++标准库的一个名字空间,很多使用的内容都是来自于标准名字空间,例如字符串std::string、std::cout...
当项目中包含using namespace std;时,代码中使用std名字空间中的内容就可以省略前面的std::
类内声明,类外定义
对于类中的成员也可以声明定义分离,如果声明定义分离,通常在类内声明,在类外定义,类外的定义需要结合作用域限定符使用。
#include <iostream>
using namespace std;
class Test
{
private:
string str = "随便";
public:
// 类内声明
Test(); // 无参构造
string get_str(); // getter
};
// 类外定义
string Test::get_str()
{
return str; // 也属于类内
}
Test::Test()
{
cout << "构造函数" << endl;
}
int main()
{
Test t;
cout << t.get_str() << endl;
return 0;
}
八、this指针
概念:this指针是一个特殊的指针,保存的是当前类的对象首地址
判断this指向:this所在的函数是哪个对象的,this指向的就是这个对象。
原理:在类内调用此类的成员,虽然不用手写this指针,但是编译器都会使用this指针来调用成员,因为成员只能由对象来调用,而this指针指向的就是当前类的对象。
应用:
利用this指针的原理,其应用有:
● 区分重名的成员变量与局部变量
● 链式调用
● 多态传参
区分重名变量:当成员变量与局部变量重名时,可以使用this指针调用成员变量。
链式调用:如果一个函数的返回值是当前类的引用,那么通常此函数需要返回一个*this,并且此函数支持链式调用。