C语言面向过程,C++面向对象。
面相过程的思维方式,它更加注重这个事情的每一个步骤以及顺序。他比较直接高效,需要做什么可以直接开始干。程序=算法+数据
面向对象的思维方式,它更加注重事情有哪些参与者,需求里面有哪些对象,这些对象各自需要做些什么事情。将其拆解成一个个模块和对象,这样会更易于维护和拓展。程序=对象+消息
- 面向对象的三个核心概念:
1. 数据封装
将一组数据和这组数据相关的操作集合封装在一起,成为对象。用户不必知道对象行为的实现细节,只需根据对象提供的外部接口访问对象。C++中,实现封装机制的是类。封装的好处是:
- 隐藏实现细节,提供公共访问方式;
- 提高代码复用性;
- 提高安全性。
2. 继承
父类抽象出共同特征,子类表达差别。子类继承父类的数据与操作,同时可以修改和扩充。
3. 多态
一个名字具有多种含义。
同一个行为具有多个不同的表现形式。
同一个接口使用不同的实例执行不同的操作。
重载表达了最简单的多态性。
- 指针和变量自增自减有什么不同?
变量自增自减改变变量的值,指针自增自减改变指针的地址。
- 宏定义与操作符的区别
宏定义是预处理命令之一,他是一个替换操作,不做计算和表达式求解,不占内存和编译时间。
- 虚函数与纯虚函数的特点
虚函数机制使得函数调用与函数体的匹配在运行时才确定。
定义和使用虚函数的过程:
- 在基类中用virtual关键字将成员函数声明为虚函数;
- 在派生类中重定义基类的虚函数,但函数原型必须完全相同;
- 定义基类指针或引用,使其指向基类或派生类对象。可以通过该指针或引用调用虚函数。
纯虚函数是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数。
拥有纯虚函数的类称为抽象类。抽象类不能被实例化,只能作为其他类的基类。
特别地,当抽象类的所有函数成员都是纯虚函数时,这个类称为接口类。
- 引用与值传递的区别
值传递传递的是一个值的副本,函数对形参的操作不会改变实参的值。
引用传递传递的对象是引用对象的内存地址,实参的值会随着形参值的改变而改变。
- 指针与引用的区别
- 引用无需解引用,指针需要解引用;
- 引用被定义时被初始化一次,之后不可改变,指针可变;
- 引用不能为空,指针可以为空;
- 程序为指针变量分配内存区域,而引用不需要分配内存区域,所以指针自增操作是指针地址的自增,引用自增操作是变量值的自增。
- 类与结构体的区别
- 结构体存储在栈中,类的实例化可以存储在栈中,也可以存储在堆中;
- 结构体的执行效率比类高;
- 结构体没有析构函数,类有析构函数;
- 结构体不可以继承,类可以继承。
- C++覆盖,隐藏,重载
返回类型 | 参数 | 说明 | |
---|---|---|---|
重载 | 无关 | (类型、个数、顺序)不同 | 同一作用域的同名函数参数不同 |
重写(覆盖) | 相同 | 相同 | 基类函数需有virtual关键字修饰 |
隐藏 | 无关 | 无关 | 隐藏参数不同的同名基类函数,或隐藏参数相同的基类非虚函数 |
- 什么是内联函数
如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。
如果想把一个函数定义为内联函数,则需要在函数名前面放置关键字 inline,在调用函数之前需要对函数进行定义。
内联函数与宏定义的区别
- 内联函数是在编译时展开,而宏在预处理时展开;在编译的时候,内联函数直接被嵌入到目标代码中去,而宏只是一个简单的文本替换。
- 内联函数可以进行诸如类型安全检查、语句是否正确等编译功能,宏不具有这样的功能;宏不是函数,而inline是函数。
- 宏在定义时要小心处理宏参数,一般用括号括起来,否则容易出现二义性。而内联函数不会出现二义性。
- 静态成员函数
静态函数是用static修饰符修饰的函数,静态函数没有this指针,只能访问静态变量。
一般使用静态成员函数来访问静态数据成员或其他静态成员函数。
- 友元函数
在类内使用friend声明函数,可以使友元函数访问类的非public成员。
友元函数本身不属于类的成员函数,因此友元函数没有this指针。
友元函数调用方法与普通函数调用方式一样。
- this指针
this指针是系统预定义的特殊指针,表示当前对象的地址。
C++为每一个非静态成员函数提供一个this指针。
实现成员函数准确操作对象的数据成员而不会误操作其他对象。
- 复制构造函数
用一个已经存在的对象去构造另一个一摸一样的对象。
对于CString类,其复制构造函数原型为:CString(CString &oldStr);
显式地定义复制构造函数避免成员指向同一块动态内存区,从而导致函数调用结束时同一块内存空间被释放两次,造成运行出错。
- 派生类的构造与析构
在创建派生类对象时:
- 首先创建基类对象
- 再初始化派生类对象成员
- 最后调用派生类自身构造函数
在派生类对象被释放时:
- 先调用派生类的析构函数
- 在调用派生类对象成员所属类的析构函数
- 最后调用基类析构函数