一、C++与C的区别
1.各自有什么特点,区别?
C++是完全兼容C,只要是合法的C的程序在C++中都是合法的!C++是C的增强版本。C++比C多了两个+,C++中扩展了很多内容,数据类型:引用、类类型、布尔类型等。编程思想是不一样的,C语言是面向过程的结构化的程序设计语言,中级语言。c++是面向对象,C语言是面向过程
2.如何判读编译器是g++还是gcc?
1.代码
#include <stdio.h>
int main()
{
#ifdef__cplusplus
printf("g++\n");
#else
printf("gcc\n");
#endif
return 0;
}
2.计算一个字符占的内存大小
二、命名空间
命名空间格式:namespace 命名空间的名字{可以有变量,也可以有函数,还可以有自定义的数据类型};
使用:命名空间名字::变量
使用using namespace命名空间名字;
三、标准输入输出流
什么是流: 以字节为单位,连续不断,方向一致的称为流!
输入流对象: cin 使用: cin>> 变量;
输出流对象: cout 使用:<< 变量;
好处: 输入输出不需要做格式的限制,使用简单
四、引用类型
1、什么是指针: 保存地址,得到地址,可以对地址中的内容做修改、访问。
什么是引用: 就是给变量起别名,变量是已经存在的,别名和变量指的是同一块内存空间!
引用: 可以实现和指针一样的效果 格式: 数据类型 &引用名 = 变量名;
引用的目的:1.弱化指针,能用指针实现的可以替换成引用!
2.减少临时空间的分配: int *p;就需要给p分配内存空间;引用是不需要分配内存空间。
2.引用与指针的区别:
1.引用是给变量起别名;指针是用来保存地址;
2.定义指针变量系统会给分配内存空间,定义引用不会额外的分配内存空间;
3.指针变量定义完之后可以不进行初始化,但是一般为了避免野指针,会初始化为NULL;
引用定义完必须进行初始化
4.指针变量是可以改变指向,但是引用一旦初始化之后不可以改变指向。使用引用比使用指针安全!
5.应用:都可以设计成函数的参数类型。
五、函数重载
1.函数重载解决的问题:函数功能相似,参数不同(参数类型不同)的一组函数,解决函数名命名困难的问题!(在C语言中不能出现同名函数)
函数重载定义: 函数名相同,函数功能要相似,参数不同(参数类型不同、参数个数不同、参数类型的顺序不同),与返回值类型无关的一组函数!
函数重载的原理: 使用g++进行编译的时候,函数名会根据参数类型以及参数个数进行重命名,函数名字不一样,函数在内存中的地址就不同,调用的时候执行的就是不同的函数体!
2,函数调用的原理:
函数定义完之后在内存中是有一块空间,编译成2进制文件,调用函数的地方存的就是函数在内存中的地址;根据地址找到对应的代码块去执行(函数名指的就是函数的地址),执行完之后再反回到调用的地方继续往下执行!
六、参数默认
什么是参数默认值:就是在函数定义的时候给了形参一个初始值。
当我们在调用函数的时候,可以选择性的给这个参数值,可以给它值也可以不给它值!如果不给它值,按默认值参与函数体中的运算;如果给了它值,就按给的值参与函数体中的运算!
当函数参数有默认值,可以解决函数重载中 只有参数个数不同的而造成的代码冗余!
在设计函数参数默认值的时候要注意:
1.参数默认值给的顺序是 从右向左的;调用函数的时候参数匹配的顺序是从左向右的!
2.在函数重载中,当函数参数有默认值的时候要注意二义性,不然就会出错!
3.当函数声明和函数定义同时存在的时候,参数的默认值只能出现一次,建议放在函数声明的地方!
七、动态内存分配
C中的动态内存分配:malloc库函数 free库函数
C++中有提供另外的动态内存分配的方法:
New运算符 –开空间 Delete运算符—释放空间
书写格式:数据类型 *指针变量 = new 数据类型; ==》 delete 指针变量;
数据类型 *指针变量 = new 数据类型[个数]; ==》 delete [] 指针变量;
new和malloc的区别?
- New是C++中的运算符,malloc是C中标准的库函数;
- 书写: new后面只要跟数据类型即可,并且开空间后不需要进行强制类型转换; Malloc开空间:要给开空间的大小,并且开空间后要进行强制类型转换;
- New开的空间用delete去释放; malloc开的空间free去做释放;
- New开的空间可以让做初始化,malloc开的空间初始化要自己用memset去做;
- 对于类类型来说,new的方式去创建对象,会自动的调用构造函数;delete释放对象的时候会自动调用析构函数;Malloc是不会执行构造函数的,free是不会执行析构函数的,
C++中的结构体与C中结构体的区别?
<1>.c结构体中不能有函数;而C++结构体中是可以有函数的!
<2>.c中空结构体的大小为0字节;C++中空结构体的大小为1字节
<3>C中的结构体面向对象不彻底,C++中面向对象,就是把属性和行为整合在一起来完整的描述一类事物! 可以用结构体,但是他有提供专门的一种数据类型类来表示的!
C++中的类与C++中结构体的区别?
<1>.关键字不同: 类是用class 结构体用struct
<2>.初始化的方式是不一样的:
结构体的初始化是 数据类型 变量名 = {};
但是类变量的初始化是不能按结构体的方式去做;
<3>.成员默认的权限是不同的:
结构体中成员的默认权限是 公共的 public
类中成员的默认权限是私有的 private
<4>结构体定义出来的变量就是变量;
类数据类型定义出来的变量叫 对象
八、类
什么是类:为了描述一类事物的属性和行为而自定义的一种数据类型!
把属性和行为整合在一起 {}
类的关键字: class
格式:
Class 类名{属性;行为};
C++中的结构体: struct 名字{属性;行为};
public: 公共的,公有的 类的外部是可以直接访问的
private: 私有的 类的外部是不可以访问的,类的内部是可以访问的!
protected: 受保护的
- 封装---面向对象编程中4大特性
把一类事物的属性和行为提取出来,用自定义的数据类型 类 包在一起,该隐藏的隐藏起来,该暴露的暴露出来!哪些是需要隐藏起来的:属性。哪些是需要暴露出来的:行为—接口
- This指针
- 类的每一个成员函数中都有一个隐藏的参数this,参数的格式:类名 *const this;
- 使用的时候,哪个对象来调用成员函数,this保存的就是哪个对象的地址;
- 在成员函数的实现过程中,如有访问到类自己的数据成员的时候建议加上this!避免因为形参名字和数据成员名字相同造成数据混乱!
- 类中特殊的成员函数--构造函数
本质:是函数;
作用:在创建对象的时候,给对象分配内存空间并对数据成员进行初始化的。
何时调用:在创建对象的时候被调用的
谁调用: 系统自动调用
如果我们自己没有定义构造函数的话,系统会帮我们自动的创建一个空的构造函数;如果我们自己有写,走我们自己定义的构造函数!
定义的格式:
无函数类型 函数名和类名是一样的
函数名(参数列表){}
什么是默认构造函数:
<1>.构造函数无参的
一种是我们自己写的;一种是系统帮我们自动生成的
<2>.有参数的构造函数,并且所有参数都有默认值!
- 类中特殊的成员函数--析构函数
本质:函数
作用:在对象生命周期结束的时候,做资源释放回收的!特别是在堆区分配的空间一定要通过free或者delete去做释放!
何时调用:在对象生命周期结束的时候
谁去调用:系统自动去调用
析构函数如果我们自己没有定义,系统会帮我们自动生成一个空的析构函数;如果我们自己写了,会调用我们自己写的析构函数!
定义格式:
无参数类型 无参 函数名和类名是一样,前面要加上~
~类名(){}
- 拷贝构造函数
拷贝构造函数分为两种:深拷贝 浅拷贝
什么是浅拷贝:单纯的把一个类对象的数据成员值赋值给另外一个类对象的数据成员
什么是深拷贝:在拷贝构造函数中对指针类型的数据成员重新new分配空间,再把数据拷贝到堆区空间中!
什么时候进行深拷贝,什么时候进行浅拷贝:如果构造函数里有在堆区开空间的话,要进行拷贝就需要进行深拷贝。系统帮我们自动生成的拷贝构造是浅拷贝构造函数;如果要进行深拷贝,拷贝构造函数一定要自己去写!
static修饰类的成员
- static修饰类的数据成员
初始化:类内声明,类外初始化
类的静态数据成员特点:
- 属于类但是不属于某一个对象;所有的对象共用一个变量
- 没有对象也可以进行访问
访问:
- 类名::变量名;
- 对象名.变量名; 指针类型对象名->变量名;
2.static修饰类的成员函数
特点:
- 静态的成员函数没有this指针;
- 静态的成员函数只能访问静态的成员,不能访问非静态成员
- 非静态的成员函数可以访问静态的成员
访问:
类名::成员函数();
对象.成员函数(); 指针对象->成员函数();
const修饰类的成员
2-1. const修饰类的数据成员
Const修饰数据成员,数据成员的值是不可以修改的!
如何初始化:
使用初始化列表的方式,在构造函数首部的后面;这个类的所有的构造函数都要用初始化列表对const修饰的数据成员进行初始化
非const修饰的数据成员也可以使用初始化列表进行初始化
2-2、const修饰的成员函数
<1>const修改的成员函数就变成了常函数,本质上修饰的隐藏起来的参数 this!
只能访问成员但是不能修改
<2>const修饰的成员函数中是不能调用非const修饰的成员函数的!
<3>非const修饰的成员函数中是可以调用const修饰的成员函数的
const修饰类的对象
const修饰的类对象(常对象),不能调用非const修饰的成员函数;只能调用const修饰的成员函数! 常对象只能调用常函数
- mutable关键字作用:
- 解决const修饰的成员函数中没法修改数据成员值的问题
-
使用: 就是在数据成员声明的前面加上 mutable
运算符重载
1、友元函数重载+运算符
2、成员运算符+重载
3、前++运算符重载
4、后置++运算符重载
5、<<运算符重载—友元重载
继承
为什么要使用继承,解决什么问题?
减少代码冗余,新写的代码中可以直接使用已经有了的代码,提高开发效率!
什么使用继承:
一个类是另外一个类的特殊版本的时候,就可以使用继承!
父类与子类
父类:已经存在的类
子类:新创建的类
继承是如何继承的呢?
子类继承父类的所有(数据成员和成员函数) 友元是否会被继承?不会被继承,因为他不是类的成员,不具有传递性!构造函数和析构函数是不会被继承!
继承的格式是什么样子的?
Class 子类名:继承方式 父类名{};
继承方式有三种:
Public继承:
Private继承:
Protected继承:
- 多态的概念
- 静态(绑定)多态和动态(绑定)多态!!!
什么是静态(静态库): 在编译阶段会链接到可执行文件中
什么是动态(动态库): 在运行阶段会链接到可执行文件中
总结: 静态和动态的区别: 链接的时刻不同
什么是静态多态:调用一个函数,在编译阶段就知道要执行的函数是哪一个
体现在:函数重载、运算符重载
G++去编译的时候,会根据函数的参数类型以及参数个数对函数进行重命名,调用的时候不同的函数名对应不同的函数体!
什么是动态多态:调用一个函数,在运行阶段才知道要执行的函数是哪一个
体现在:继承、虚函数
绑定:调用函数的语句与函数体进行绑定
总结一下实现动态多态的条件:
- 一个父类多个子类
- 继承关系中,子类要重写父类的虚函数;函数首部是一模一样
- 用父类的指针或者引用去操作子类对象,调用虚函数才会触发动态!
重定义、重载、重写的区别
重定义(隐藏): 在继承关系中,子类有和父类同名的成员函数,父类的函数被隐藏了!同名:函数名相同即可!
不加virtual是重定义
何时重定义: 父类的成员函数实现的效果满足不可子类需求
重写(覆盖): 在继承关系中,子类重写父类的虚函数,父类的虚函数在这个子类中被覆盖了!
函数的首部是一模一样的!
重载: 必须在同一个作用域中, 函数名相同,功能相似,参数不同,与返回值类型无关的一组函数互为重载!
- 空类对象占内存大小
空类中有默认的6个成员函数:
默认构造函数、析构函数、拷贝构造函数、=赋值运算符、&运算符、&运算符 const
关键字
- Explicit
作用: 防止构造函数单参数时进行类型转换
构造函数的分类:
默认构造函数、拷贝构造函数、转换构造函数、普通构造函数(参数在2个或者2个以上的)
2。Final关键字
作用:就是用来修饰类以及类的成员函数的
特点: <1>final修饰类,这个类不能被继承
<2>Final修饰虚函数的时候,虚函数是不可以被重写的!
3.Inline关键字
作用:用来修饰函数,类的成员函数用inline,变成了内联函数!
- 类型转换函数
C中的类型转换方式:
<1>隐式类型转换 <2>强制类型转换 (类型)表达式 类型(表达式)
C++中的类型转换函数---函数模板
- 异常处理
什么是异常:编码过程中遇到的报错!
编码过程中遇到的错误:
- 编译错误(语法错误)
- 运行时错误(逻辑错误):数组越界、野指针、打开文件失败、动态开空间、打开数据库等等!
避免逻辑错误:
用返回值来做判断!
C++中引入了专门处理异常的机制:
Try{可能会出现异常的代码}Catch(异常类型){捕获异常} catch(){}throw 来抛出异常的!
特性:
- 抛出各种类型的异常,自定义的也有系统提供的类型
- 跨级处理异常
- 三个关键字: try、throw、catch
单例模式—数据库
单例设计的三大特性:
- 唯一的对象由这个类它自己去创建;构造函数私有化
- 提供静态的成员函数去获取到唯一的对象
- 静态的数据成员来保存唯一的对象
单例模式又分为两种:
懒汉模式:需要的时候才去准备的;
饿汉模式:一开始就准备好了,以防万一!存在的问题:万一没有用到了的话,也开辟了空间!