一、面向对象与面向过程:
面向过程:关注解决问题的步骤,算法。
面向对象:关注的是谁能解决问题,需要什么样的数据(成员变量),具备什么样的功能(成员函数)。
抽象:找出或相像出一个能够解决问题的"对象",通过研究观察对象,找出c"对象"解决问题所必须的数据(属性)、功能(技能)。
封装:把抽象的结果归纳为一个结构,然后实例化出结构变量,然后结构变量中的数据和功能相互作用最终解决问题。
继承:在封装结构时,可以先分析结构需要的数据和功能现有的结构是具备,如果具备,可以继承现有的结构的代码,达到代码复用的目的。
多态:指的是结构的多种形态,一个对象发出指令后,该对象可以实际情况作出反应,这就是多态。
二、类和对象
注意:C++中的结构和类没有本质的区别,但为了与C语言中的结构区分,一般使用类型进行编程。
类:一种既能表示属性又能表示行为的复合数据类型。
对象:就是类这种数据类型的创建出的实例,相当于结构变量。
三、类的设计和实例化
1、类的一般形式
class ClassName : 继承方式 父类
{
private:
// 成员变量
public:
// 成员函数
protected:
// 查漏补缺
};
2、类访问控制限定符
public: 公有成员,成员可以在任何位置被访问。
private: 私有成员,成员只能在类的成员函数中访问。
protected: 受保护成员,成员只能在类中和子类中的成员函数中访问。
注意:类成员默认是私有的,结构成员默认是公有的。
3、对象的实例化方法
在栈上创建:类名 对象;
在堆上创建:
类名* 指针 = new 类型名;
类名* 指针 = new 类型名[n]; // 实例化多个类对象
注意:对象只能通过构造函数初始化,可以在实例化对象时给对象传参
4、类的声明、实现、使用
1、在头文件中声明类型
class 类名:继承方式 父类
{
// 成员变量
public:
// 声明成员函数
返回值 函数名(形参列表);
// 构造函数
~类名(形参列表);
// 析构函数
~类名(形参列表);
};
2、在源文件中实现相关函数
返回值 类名::函数名(形参列表)
{
// 函数的功能实现,此位置还相当于在类中
}
3、使用类时只需要包含头文件,然后源文件的目标文件一起链接,最终生成可执行文件。
4、如果类的内容不多,可以考虑在头文件中完全实现,不用写源文件。
三、构造函数
1、什么是构造函数:类的同名成员函数,没有返回值,参数创建对象时提供,可以被重载。
2、什么时候调用、谁调用、调用几次:
创建对象时时候,对象自己自动调用,在整个对象的生命周期中至少也只能调用一次。
3、负责干什么:
负责类成员的初始,分配相关资源,设置对象的初始状态,总之做一准备工作。
4、如果没有显式实现构造函数,编译器会生成一个什么都不做的无参构造,如果显示实现了构造函数,默认的无参构造就不再生成。
编译器生成无参构造的目的就是为了避免错误。
可以为有参设置默认形参,达到无构造的效果。
注意:编译器会自动生成四个成员函数(构造函数,析构函数,拷贝构造,赋值构造),这四个函数并不真正语法意义上的函数,而功能意义上的函数。
5、对象的创建过程
1、先分配内存资源,无论栈还是堆。
2、传递实参调用构造函数,完成如何任务:
A、执行初始化列表
B、根据继承表依次调用父类的构造函数。
C、根据成员变量定义顺序依次执行成员变量的构造函数。
D、执行构造函数中的代码。
注意:执行构造函数中的代码是整个构造过程的最后一步,这样设置是为了让构造函数代码所需要的一切资源和先决条件在代码执行准备好。
6、初始化列表
构造函数(形参列表):成员1(参数1),成员2(参数2)
{
构造函数代码
}
注意:如果成员变量具有const属性,必须使用初始化列表进行赋值,还可以在此处显现调用父类、成员的有参构造。
7、单参构造
如果构造函数只有一个参数,那么 类型 对象=val 语句就不会报错,它就具备了自动调用单参构造达到类型转换的效果。
如果想禁止这种类型转换功能,可以在单参构造函数前加关字 explicit
四、析构函数
1、什么是析构函数:类的成员函数,没有参数和返回值,也不可以重载。
class ClassName
{
public:
ClassName(...) // 构造函数
{
}
~ClassName(void) // 析构函数
{
}
}
2、什么时候调用、谁调用、调用几次:
类对象销毁的时候由对象自己自动调用,在对象的生命周期中最多调用一次。
如果对象存储在堆内存,没有显式delete析构函数不会被调用。
也可以被显式手动调用,这样析构函数执行多次,但不符合情理,也可能出现错误。
3、析构函数负责做什么
释放资源,保存数据,总之做一些收尾性的工作。
4、缺省析构
编译会默认生成一个析构函数,它负责释放类成员,一般情况类中如果没有使用堆内存资源,也不需要保存数据,缺省析构完全够用。
5、对象的销毁过程
注意:对象和销毁过程与创建过程是相反的。
创建:分配内存(对象)->调用构造函数->父类构造->成员构造->执行构造函数(分配堆内存)。
父类构造的执行顺序按继承表执行。
成员构造的执行顺序安定义的先后顺序执行。
销毁:调用执行析构函数(销毁堆内存)->成员析构->父类析构->销毁内存。
父类析构的执行顺序按继承表逆序执行。
成员析构的执行顺序按定义的先后顺序逆序执行。
练习1:封装顺序的栈和队列类,在头文件中实现即可。
练习2:使用面向对象编程思想实现五子棋,声明和实现拆分。
练习3:封装NetWork类,然后使用它实现TCP和UDP的回声服务器。