01 C++类&对象
类定义是以关键字 class
开头,后跟类的名称。
- 它定义了类的对象包括了什么,以及可以在这个对象上执行哪些操作。(即成员变量和成员函数)
访问数据成员
- 类的对象的
公共public
数据成员可以使用直接成员访问运算符 (.
) 来访问。 - 私有的成员和受保护的成员不能使用直接成员访问运算符 (
.
) 来直接访问。
概念
- 类成员函数
- 类访问修饰符
- 构造函数&析构函数
- C++拷贝构造函数
- C++友元函数
- C++内联函数
- C++中的
this
指针 - C++中指向类的指针
- C++类的静态成员
02 C++继承
继承允许我们依据一个已有类(基类)来定义一个新类(派生类)。
- 继承代表了
is a
关系。例如,哺乳动物是动物,狗是哺乳动物,因此,狗是动物,等等。 class derived-class: access-specifier base-class
- 其中,访问修饰符
access-specifier
是public
、protected
或private
其中的一个;base-class
是之前定义过的某个类的名称。- 如果未使用访问修饰符
access-specifier
,则默认为private
。
访问控制和继承
- 派生类可以访问基类中所有的非私有成员。因此基类成员如果不想被派生类的成员函数访问,则应在基类中声明为
private
。
我们可以根据访问权限总结出不同的访问类型,如下所示:
访问 | public | protected | private |
---|---|---|---|
同一个类 | yes | yes | yes |
派生类 | yes | yes | no |
外部的类 | yes | no | no |
一个派生类继承了所有的基类方法,但下列情况除外:
- 基类的构造函数、析构函数和拷贝构造函数。
- 基类的重载运算符。
- 基类的友元函数。
继承类型
当一个类派生自基类,该基类可以被继承为 public
、protected
或 private
几种类型。继承类型是通过上面讲解的访问修饰符 access-specifier
来指定的。
- 公有继承(
public
):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员来访问。 - 保护继承(
protected
): 当一个类派生自保护基类时,基类的公有和保护成员将成为派生类的保护成员。 - 私有继承(
private
):当一个类派生自私有基类时,基类的公有和保护成员将成为派生类的私有成员。
多继承
即一个子类可以有多个父类,它继承了多个父类的特性。
class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>
{
<派生类类体>
};
03 C++ 重载运算符和重载函数
重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列表和定义(实现)不相同。
C++ 中的函数重载
在同一个作用域内,可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同。您不能仅通过返回类型的不同来重载函数。
C++ 中的运算符重载
重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。
名称 | 符号 |
---|---|
双目算术运算符 | + (加),-(减),*(乘),/(除),% (取模) |
关系运算符 | ==(等于),!= (不等于),< (小于),> (大于>,<=(小于等于),>=(大于等于) |
逻辑运算符 | ||(逻辑或),&&(逻辑与),!(逻辑非) |
单目运算符 | + (正),-(负),*(指针),&(取地址) |
自增自减运算符 | ++(自增),–(自减) |
位运算符 | |(按位或),& (按位与),~(按位取反),^(按位异或),,<< (左移),>>(右移) |
赋值运算符 | =, +=, -=, *=, /= , % = , &=, |
空间申请与释放 | new, delete, new[ ] , delete[] |
其他运算符 | ()(函数调用),->(成员访问),,(逗号),[](下标) |
.
:成员访问运算符.*
,->*
:成员指针访问运算符::
:域运算符sizeof
:长度运算符?:
:条件运算符#
: 预处理符号
🐷了解运算符重载实例
04 C++多态
C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。
- 有了多态,您可以有多个不同的类,都带有同一个名称但具有不同实现的函数,函数的参数甚至可以是相同的。
虚函数
虚函数是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。
我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定。
纯虚函数
您可能想要在基类中定义虚函数,以便在派生类中重新定义该函数更好地适用于对象,但是您在基类中又不能对虚函数给出有意义的实现,这个时候就会用到纯虚函数。
= 0
告诉编译器,函数没有主体,该虚函数是纯虚函数。
05 C++ 数据抽象
它们向外界提供了大量用于操作对象数据的公共方法,也就是说,外界实际上并不清楚类的内部实现。
访问标签强制抽象
数据抽象的好处
- 类的内部受到保护,不会因无意的用户级错误导致对象状态受损。
- 类实现可能随着时间的推移而发生变化,以便应对不断变化的需求,或者应对那些要求不改变用户级代码的错误报告。
设计策略
抽象把代码分离为接口和实现。
所以在设计组件时,必须保持接口独立于实现,这样,如果改变底层实现,接口也将保持不变。
06 C++ 数据封装
- 封装是面向对象编程中的把数据和操作数据的函数绑定在一起的一个概念,这样能避免受到外界的干扰和误用,从而确保了安全。
- 数据封装引申出了另一个重要的 OOP 概念,即数据隐藏。
- 数据封装是一种把数据和操作数据的函数捆绑在一起的机制。
- 数据抽象是一种仅向用户暴露接口而把具体的实现细节隐藏起来的机制。
C++ 通过创建类来支持封装和数据隐藏(public
、protected
、private
)
通常情况下,我们都会设置类成员状态为私有(
private
),除非我们真的需要将其暴露,这样才能保证良好的封装性。
07 C++ 接口(抽象类ABC
)
接口
描述了类的行为和功能,而不需要完成类的特定实现。- C++ 接口是使用抽象类来实现的。如果类中至少有一个函数被声明为纯虚函数,则这个类就是
抽象类
。 - 纯虚函数是通过在声明中使用 “= 0” 来指定的。可用于实例化对象的类被称为
具体类
。
我能否这样说?
- 基类就是抽象类,派生类就是具体类
- 抽象,接口,封装之间的关系很容易混淆