C++ 特性:
1.构造函数:
1)构造函数最主要的功能是创建对象本身。(给对象分配内存空间)
2)C++规定, 每个类必须有一个构造函数, 如果没有构造函数, 就不能创建任何对象。
3)C++还规定, 如果一个类没有提供任何的构造函数, 则C++提供一个默认的不带参数的构造函数(由C++编译器提供), 该构造函数只负责创建对象, 不负责任何的初始化工作。
4)只有一个类定义了一个构造函数, 无论这个构造函数是否是一个带参数的构造函数, 编译器都不会再提供默认的构造函数。
故如果一个类定义了一个带参数的构造函数, 还想要无参数的构造函数, 则必须我们自己定义。
5)构造函数都是和类名同名, 且无返回值的函数。 我们可以有多个构造函数。(参数不同, 构造函数重载)
2.析构函数
1)析构函数, 与类名同名, 但前面多一个~符号。
2)析构函数是一个构造函数的反向过程, 主要是进行对对象内存空间的销毁或回收。一般当我们函数结束后系统会自动调用析构函数, 将该对象内存空间进行回收。 同样, 当我们进行delete 对象时, 也会调用析构函数, 对对象内存空间进行回收。
3.重载
1)重载构成的条件: 函数的参数类型、参数个数不同, 才能构成函数的重载。(以编译器的角度去考虑改问题。)
2)重载包括函数重载和操作符重载。
4.this指针
1)this指针是一个隐含的指针, 它是指向对象的本身,代表了对象的地址。(每个对象都有它的一个隐含的this指针)
2)一个类所有的对象调用的成员函数都是同一代码段。 那么成员函数又是怎么识别属于统一对象的数据成员呢?原来, 在对象调用pt.output(10,10)时, 成员函数除了接受2个实参外, 还接受到了一个对象s的地址。 这个地址被一个隐含的形参this指针所获取, 它等同于执行this=&pt。 所有对数据成员的访问都隐含地被加上前缀this->。 例如x=0;等价于this->x=0.
5.继承
1)Public Protected Private 三种属性:
Public 是共有的属性, 外部可以访问。
Protected 是受保护的属性, 子类可以访问。
Private 是私有的属性, 不允许外部访问, 包括子类也不能访问。
继承关系同样有以上三种。
Public继承,Protected继承,Private继承:
Public继承继承所有父类的属性。
Protected如果继承Public的父类则变成Protected属性, Protected依然是Protected。
Private继承则全变成Private属性。
三者共同的是对父类的Private属性都无法访问。
2)继承是用于父类子类(或基类派生类)之间的关系。允许某给类继承其他类的属性。
语法:
Class 派生类名称:访问权限 基类名称
{
......
}
分类 多重派生, 一个父类对应多个子类。 多继承, 一个子类多应多个父类。 多层派生类, 子类继承于子类。
3)函数的覆盖
函数的覆盖和函数的重载不同,函数的重载是发生在父类与子类之间, 子类认为父类的方法不太合适, 重新写了一个方法, 覆盖了父类的方法。 而重载是对同一个类中的一个方法进行重载。
6.友元函数
通常情况下, 只有类中的成员函数才可以访问本类中的私有数据类型和保护数据类型。
但C++也提供了一种特殊的函数----友元函数, 允许访问类的私有数据类型和保护数据类型。
必须在类中friend 声明。
类似于goto, 给我们的代码增加了灵活性, 但不提倡使用。
7.多态性(playmorphism) 指的是一个接口名称具有多种功能, 是面向对象设计的重要特性。
其实函数的重载和虚拟函数都是C++多态性的体现。
但函数的重载是编译时的多态性。
虚拟函数是运行时的多态性。
如下例子
如上例所示, 如果我们声明一个基类指针, 则无论我们指向哪个类, 最终调用的成员函数都是基类的。
虚拟函数解决了这个问题, 实现了函数在执行过程中的多态性。(一种接口, 多种功能)
当C++编译器在编译的时候, 发现Animal类的breathe()函数是虚函数, 这个时候C++就会采用迟绑定(late binding)
的技术, 在运行时, 依据对象的类型(在程序中, 我们传递的Fish类对象的地址)来确认调用的哪个函数, 这种能力就叫做C++的多态性。
不加virtual的话, 则该函数会被早期绑定, 即编译时就绑定了。识别了virtual关键字后, 编译器就不对该函数进行绑定, 而是运行时根据对象的类型(属于哪个类)进行绑定。即一个为编译时绑定, 一个是运行时绑定。
8.纯虚函数
1)纯虚函数---指的是将一个虚函数赋为0, 而没有函数体。如virtual void display()=0。
纯虚函数所在的类是一个抽象类。(abstract class)无法实例化一个对象。
一般我们在子类当中去具体实现它。
纯虚函数一般用于我们只是建立一个为子类服务的抽象基类, 而不是去具体实例化它的情况。
9.引用和指针
引用是一个变量的别名。如
int a=3;
int &b=a;
b即为a的一个别名, 当我们改变a时, b也随之改变。 a作为int型变量, 其实只是在编译过程中, 编译器给a分配了一个int大小的内存空间。(如果是全局变量即分配了SRAM的一块空间, ARM连接器一般会该变量生成一个smybol, 如果是局部变量, 可能就仅仅只是分配了以个寄存器对其进行操作, 或者是分配栈区的一块区域存放a) 即a这个字符本身并不占用内存空间, 同样b字符本身也不占用, 仅仅是a的别名而已。
p.s 引用通常并不用做上述例子, 容易产生混淆, 引用通常作为函数传参。
指针
int a=3;
int *p=&a;
指针本身是一个变量, 只不过是一个存放地址的特殊变量。对p本身, 编译器是给它分配了一快内存空间的(在32位机器上通常是4byte空间), 然后它里面存放了一个地址, 指向变量a。