note/程序开发/编程语言/C++/C++ 基础.md
2023-07-05 09:34:06 +08:00

10 KiB
Raw Blame History

绪论

程序语言

  • 机器语言
    • 0 、1组成
  • 汇编语言
    • 助记符组成
    • 直接操作寄存器
  • 高级语言
    • 接近自然语言
    • 屏蔽机器细节

C++

1970 年 C ----> 1983 年 C with Class

特性

  • 虚函数 、操作符重载
  • 多重继承 、模板
  • 异常处理 、 名字空间
  • RTTI

向下兼容

C++ = C + 不完全的面向对象

new 与 delete 内存泄漏

允许多继承,关系复杂

面向对象

  • 数据 + 操作 = 对象
  • 抽象程度高

面向过程

  • 函数的排列组合
  • 抽象程度低

信息

数字系统

  • R 进制 转 十进制

    • 各位数字与它的权相乘,其积相加
  • 十进制 转 R 进制

    • 整数 除R取余
    • 小数 乘R取整
  • 10 = 012 = 0xA

数字编码

  • 原码
    • 符号位 + 绝对值
    • q = +k 与 -k
    • 负号 0 正号 1
  • 反码
    • q = +k 与 M - k - 1
    • 负数的数字位取反
  • 补码
    • q = +k 与 M - K
  • 浮点数
    • 1 + 8+ 23
    • 1 + 11 + 52
  • 定点数

数据类型

数据初始化

p [ptr->data] class

*p [data] class

  • 常量
    • 常量在定义时就必须赋初值
    • 常量指向的数据不可变
  • 指针
    • p 指向数据的地址
    • *p 取数据
  • 内置变量
    • 函数内未定义
    • 函数外为0
    • 列表初始化
    • 圆括号初始化
    • 拷贝初始化
    • 直接初始化
    • 内置类型被初始化为0
    • 类类型由构造函数初始化

特殊类型

常量

声明时必须赋值 (指针除外)

不可以改变常量的值

const 定义后的内容不可变

const 常量指向 地址

宏常量指向文本

const float PI = 3.14;

//const 后的内容不可变
const float PI = 3.14;
int const radiu = 1;
//XXX const int size; PI = 3.14159;

//常指针 *p1 不可变p1可变
int const *p1;
//指针常量 p2 不可变 必须赋初值,*p2可变
int i = 0;
int * const p2 = &i;
//常指针常量 指向常量的常指针
const int * const p3 = &radiu;
//常引用
const int& p4 = radiu;

enum Weekday {SUN=7, MON=1, TUE=1, WED, THU, FRI, SAT};
//const int SUN = 7;....

枚举

enum Weekday {SUN=7, MON=1, TUE=1, WED, THU, FRI, SAT};

常量的集合,默认为文件作用域

类型关键字

类型转换

  • 类型转换操作符
    • const_cast
    • static_cast
    • dynamic_cast
    • reinterpret_cast

typedef

为一个已有的数据类型另外命名-类型定义

typedef 已有类型名 新类型名表;

auto decltype

decltype(i) j = 2;

sizeof

  • “类型名”所指定的类型所占的字节数
  • “表达式”的结果类型所占的字节数

由编译器推测,数组在定义内和参数有不同大小

先求类型,再求类型所占字节数

运算符

  • =
    • a = 10
    • (a = 10 ) = 10
    • a = (a = 10)
  • ,
    • 表达式a , b = b
    • 分隔符int a, b
  • ++/--
    • i++ 与 ++i

函数

函数声明和函数原型

函数参数

值传递

单向传递,拷贝后和实参无关联

对象是值传递

引用传递

用于函数通信

节省开销

可变参数

void log_info(initializer_list<string> lst) {
	for (auto& info : lst)
		cout << info << ' ';
	cout << endl;
}
log_info({ "“Hello”", "”world”", "“!”" });

缺省参数

在函数声明中定义参数值

不可重复定义,没有声明就放函数原型中定义

函数缺省值必须位于最后

缺省参数不参与函数重载

内联函数

用来替代宏函数

用关键字 inline 修饰 函数

似乎对函数内容有限制

函数重载

相同作用域内声明相同的函数名

通过形参和名字来区分函数

const 修饰符也用于区分函数

特性

  • 封装
    • 数据和函数封装成对象
    • 封装成员的访问权限
  • 继承
  • 多态

访问控制

访问控制符

class 默认访问控制是 private

struct 默认访问控制是 public

  • public
    • 外部访问的接口
  • protected
    • 子类可访问
  • private
    • 只允许本类访问

可访问成员

不可访问的成员不可见

  • 类内
    • 可直接使用成员名访问
  • 类外部
    • 对象名.成员名
    • 类名::成员名

静态标识

在 class 中声明的静态变量是全局变量,需要在类外定义。

静态成员函数只有静态成员变量可见

函数

在类的声明中定义函数原型

非静态函数中隐含this指针指向自身对象

内联函数

类声明里的函数都是内联函数

构造函数

在对象创建时由系统自动调用

如果没有定义:

系统会自动创建一个参数为空的构造函数

函数名与类名相同 没有返回值

析构函数

若析构函数不是虚函数,系统自动调用当前类的析构函数,而调用不到子类的析构函数

虚函数会增加虚指针和虚函数表

在对象销毁时由系统自动调用自身析构以及成员对象析构

如果没有定义:

系统会自动创建一个参数为空的析构函数

函数名与类名相同 没有返回值

拷贝构造函数

形参为本类的对象引用

在对象赋值时系统会自动调用 (赋值的原理是拷贝构造函数)

如果没有定义:

系统会自动创建一个参数为空的拷贝构造函数

对象继承

对象 = 虚函数表指针 + 成员变量

子类对象 = 虚函数表指针 + 父类成员变量 + 子类成员变量

派生类继承了基类中的所有成员 构造函数、析构函数、友元函数除外

继承方式

子类继承父类的 public 和 protected 成员

并且修改访问权限

新访问权限 = 继承方式 * 旧访问权限

  • 公有继承
    • 继承后的成员的访问权限不变
  • 保护继承
    • 继承后父类的public成员变为protected成员
  • 私有继承
    • 继承后父类的public 、 protected成员变为private成员
  • 虚继承
    • 有对象组合改为指针组合,指针实例在对象的末尾的位置创建
    • 公共基类只有一份拷贝
    • (增加了虚表)

类型转换

子类可以替换父类

类和对象

前向引用声明

声明标识符

类声明

class 默认访问控制是 private

在类里定义数据成员和初值

在类的声明中定义函数原型和内联函数

对象构造

从下到上

构造组合对象{

父类对象:父类继承顺序

构造父类组合对象

属性对象:属性声明顺序

构造自身:把前面的对象组合起来

}

对象析构

和构造函数顺序相反

从上到下

多态性

发出同样的消息,被不同类型的对象接收,有可能导致完全不同的行为

一个接口,多种方法

实现方式

确定绑定的方法

静态多态性

在编译连接阶段就能完成绑定工作的情况

  • 函数重载

  • 模板

    函数模板用来创建通用功能的函数,以支持多种不同形参 进一步简化重载函数的函数体设计

  • 运算符重载

    • 后置 ++ 需要一个 int 参数

动态多态性

在程序运行阶段才能完成绑定工作的情况

  • 虚函数
    • 函数重名覆盖是依据静态类型,编译器自动重载的
    • 对于动态类型,不能实现多态,需要虚函数
    • 虚函数是实现运行时多态性基础

多态的类型

  • 重载多态

  • 强制多态

    • 强制多态是指对变量进行强制类型转换,使其符合函数、操作的要求
  • 包含多态

    • 包含多态是类族中定义在不同类中的、同名函数的多态行为,通过虚函数实现
  • 参数多态

    • 参数多态与类模板相关联,在使用时必须指定实际的类型才能实例化

模板

函数模板

类型名可作为参数

编译器只检测<>内参数是否匹配

templateName<param1 , param2 ...>( params)

类模板

  • 使用类模板可以为类声明一种模式,使得类中的
    • 数据成员
    • 成员函数的参数
    • 成员函数的返回值
  • 能取任意类型,包括
    • 基本数据类型
    • 自定义类型

虚函数

override

声明显式函数覆盖,在编译期间发现未覆盖的错误。

数据共享和保护

作用域

  • 同名隐藏

    • 标识符冲突,若作用域嵌套,则识别为内层标识符,外层该标识符不可见
  • 作用域分辨符 ::

    • 访问被隐藏的标识符

块中声明的标识符

起于块终于块

生存周期和块一致

块外无法访问

定义在类中的标识符

public 标识的接口 可以在类外访问

生存周期和类一致

文件

全局标识符

若有在文件外访问,需要添加修饰符 extern

生存周期和程序一致

命名空间

解决类名函数名冲突

namespace ouc{
    
}
using namespace ouc;

限定枚举

限制枚举值的作用域

变量生存期

静态变量

全局变量、static 变量

  • 静态生存期
    • 生存期与程序相同
  • 静态变量只初始化一次,且作用域内唯一

动态变量

块作用域、非static变量

  • 动态生存期
    • 生存期与作用域一致

类的共享 -- 友元

将模块 A 声明为模块 B 的友元 A 成为 B 信任的模块 A 能够引用 B 中被隐藏、封装的信息

友元函数

友元函数声明 = friend + 函数声明

友元类

友元类声明 = friend + 类声明

数据保护

const 修饰符

  • 修饰变量

    • 保护变量不被修改
  • 修饰成员变量

    • 只能在构造函数外的初始化列表中赋初值
  • 修饰成员函数

    • 不更新类对象
    • 参与函数重载

数据结构

数组

线性数据结构

数组名是常量指针,内存空间连续

静态数组

动态数组

程序设计

组合和继承能实现设计代码重用

输入输出流

常用流

  • ostream istream

  • ofstream iftream

  • ostringstream istringstream

流运算符

  • cin >> &a;从流中提取 >>流提取运算符

  • cout<< a;向流中插入,流插入运算符

cout cin 常用函数

默认右对齐

  • 设置宽度 setw 、width
  • 设置填充字符 setfill
  • 设置进制 dec、oct 、hex
  • 设置对齐方式 setiosflags(ios_base::left)
  • 设置有效位数 setprecision

异常

特殊的返回值 和捕获流程

异常对象为自定义任意类型 的对象

throw 异常对象;

try{

}catch(异常对象){

捕获异常

}