# typedef
typedef 并不是简单的宏替代。
- 定义一种
类型的别名
- 定义
struct结构体别名
- 用 typedef 来定义与
平台无关
的类型- 为
复杂的声明
定义一个简单的别名
,表示的是一个指向函数的指针
- 用
typedef
可以定义各种类型别名
,但不能定义变量 - 使用 typedef 便于
程序的通用
- 用
typedef
只是将一个已经存在的类型用一个新的名称
替代 typedef不
能添加新类型
# typedef
和 #define
区别
typedef
是一种类型别名
,而#define
只是宏定义
,二者并不总是
可以互换
的。
# 比较函数
C++ 的比较函数适用于
整型字符串浮点数
等多种类型。
# max
返回队列中的
最大值
,参数两个
参数,如果想要多个参数
,使用大括号初始化列表容器
的形式可以,但相比于直接两个两个比较比较耗时
#include <iostream> | |
#include <algorithm> | |
using namespace std; | |
int main(void) | |
{ | |
float a = 1.359; | |
float b = 1.823; | |
float c = 1.829; | |
auto result = max({ a, b,c }); | |
cout << result << endl; | |
return 0; | |
} |
# min
返回
队列
中的最小值
# minmax
算法标头的库函数,用于查找
最小和最大值
,它接受两个值并返回一对最小和最大值,该对中的第一个
元素包含最小值
,并且该对中的第二个
元素包含最大值
该函数包括
<algorithm>
头文件,
#include <iostream> | |
#include <algorithm> | |
using namespace std; | |
int main(void) | |
{ | |
// 字符串类型同样应用于比较,会以 ASCII 码值进行对比 | |
int a = -10; | |
int b = -20; | |
auto result = minmax(a, b); | |
cout << "最小值" << result.first << endl; | |
cout << "最大值" << result.second << endl; | |
return 0; | |
} |
# 友元
在函数前加
friend
友元
不
是成员函数
,但是它可以访问类中
的私有
和保护
成员。提高了程序的
运行效率
,但是破坏了类的封装和隐藏,使得非成员函数可以访问类的私有成员。
友元具有
不对称性
,即 A 是 B 的友元,但 B 不一定是 A 的友元,单向的
,不具有交换性友元关系
不具传递性
友元关系
不能被继承
# main 参数
main 函数有三个参数,
argc
,argv
,envp
int main(int argc,char*argv[],char*envp[]) | |
{ | |
} | |
// **int argc: 存放了命令行参数的个数 | |
//char argv [] 是个字符串的数组,每个元素都是一个字符指针,指向一个字符串,即命令行中的每一个参数 | |
//char envp [] 也是一个字符串的数组,这个数组的每一个㢝是指向一个环境变量的字符指针 |
# 题
float
,double
,long double
等类型不允许
直接进行位与
操作符如
float取地址
(也是符号) 转换为unsigned int
类型,再用取值操作符 (*
), 编译器会识别为unsigned int类型
使用
int short long移位
时,最好加上unsigned
,这样就是汇编中规律移位
(即全部移位)加入不加 unsigned,正数全是规律
移位
,负数左移
保持符号位为1
,右边补0
,负数右移时保持符号位为1
,左边补1
,所有 - 1 无论怎么右移都是 - 1位与操作符的操作优先级小于 移位操作符,但移位操作符小于取地址操作符 (取值操作符 *・*)
# static
静态数据成员
类内定义
,就必须在类外初始化
。
特点
:
- 所有成员都
共享
数据成员,只有一份内存
- 必须在
类外
进行初始化
# 静态数据成员的内存?
存放在内存的全局区
# 基类的静态数据成员不能被继承
- 继承:继承是
一个类
从另一个类
获取成员变量
和成员函数
的过程 (子类继承父类)继承特性:
继承
访问不
了父类
私有属性- 但是
私
有继承已经被
继承,被编译器隐藏
- 静态成员属性不会被继承 (属于全部对象)
- 创建子类时,
构造函数
的调用,先父类后子类
,析构
时:先子类后父类
构造函数
,析构函数
,赋值操作符
不能被继承无论什么继承,子类
都
可以访问基类中
的公共保护
成员,但子类对象
就只能访问子类的公共成员
在析构时:
- 当
释放子类
的指针对象时,会调用子类和父类
的析构函数- 当释放子类的指针对象时,只会调用
父类的析构函数
#include <iostream> | |
using namespace std; | |
class person// 父类 | |
{ | |
public: | |
person() { cout << "person的构造函数" << endl; } | |
~person() { cout << "person析构函数" << endl; } | |
}; | |
class son :public person | |
{ | |
public: | |
son() { cout << "son的构造函数" << endl; } | |
~son() { cout << "son的析构函数" << endl; } | |
}; | |
int main() | |
{ | |
son* s = new son;// 定义一个子类指针 | |
person* p = s;// 父类指针指向子类 | |
//delete s;// 释放子类内存 // 会调用子类和父类的析构函数 | |
delete p; // 释放父类 只会调用父类的析构函数 | |
return 0; | |
} |
# 据成员 为
什么必须 类外初始化
静态数据成员
也属于静态变量
,属于静态全局区
,全局区的变量,随着程序生死。而对象
不是全局静态区的,是有生命周期的
。由于生命周期的不同,所以必须在类外初始化,来解决类的生命周期问题。
static
加强了访问控制
的全局变量
,不
被继承
- 类和子类对象,
static
变量占有
一份内存
# 结构体内存
结构体内存规则
- 第一个成员在与结构体变量
偏移量为0
的地址处
其他成员变量
要对齐到对齐数的整数倍
的地址处
对齐数
=min (编译器默认的对齐数,该成员大小)
- 结构体
总大小
为最大对齐数
(每个成员变量都有一个对齐数
) 的整数倍
- 如果
嵌套了结构体
的情况,嵌套的结构体对齐
到自己大的最大对齐数的整数倍处
,结构体的整体大小
就是所有最大对齐数
(函嵌套结构体的对齐数) 的整数倍
# C 语言
# 变量类型
register
:建议编译器
将该变量放入CPU
。
# 函数 类型缺省
- 返回值
- C 语言,如果函数
未指定
返回值类型,则・默认
为int
- C++ 如果函数
没有返回值
,默认类型必须指定为void
- C 语言,如果函数
- 参数列表
C语言
,如果函数没有指定参数列表,返回值类型必须指定为 voidC++
中,有严格的类型检测
,没有参数列表的函数默认为void
,不
接受任意参数
- 缺省参数
C不支持
C++支持
,如果没有指定实参则使用缺省值,有则使用指定实参- 默认实参必须在
参数列表的结尾
- 默认参数只能出现在函数声明或者定义二选一中
- 缺省值
必须
是常量或全局变量
- 缺省参数必须是
值传递
或者常参传递
- 默认实参必须在
- 函数重载
- C: 不支持
- C++:支持
# 转义字符
\t
表示横向指标\v
表示竖向制表\b
表示退格\r
表示回车\f
表示换页\?
表示问号字符\0
表示空字符(null)
# 指针大小
指针
,在64bit
的机器中是8字节
,int 4
字节
# 读取
getchar
: 读取一个字符
。%2d
: 读取数字
,限定
两个字符,如读取的指针位置后面
出现字母忽略掉
,前面
出现字母将全部忽略
,指针移动到读取截止为止。
#define _CRT_SECURE_NO_WARNINGS | |
#include <stdio.h> | |
int main() | |
{ | |
char c1, c2; | |
int a1, a2; | |
c1 = getchar(); // 读取第一个字符 1 | |
scanf("%2d", &a1); // 读取宽度为两个,int 型,只读取 2 | |
c2 = getchar(); // 读取 a | |
scanf("%3d", &a2); // 宽度为 3,读物 345 | |
printf("%d,%d,%c,%c\n", a1, a2, c1, c2); | |
return 0; | |
} | |
/* | |
输入: 12a345b789 | |
输出: 2,345,1,a | |
*/ |
# 优先级
成员选择符
->
的优先级比前置++
,和后置++
都要高
# 字符串未赋值部分
#define _CRT_SECURE_NO_WARNINGS | |
#include <stdio.h> | |
int main() | |
{ | |
int a[3][3] = { {1,2},{3,4},{5,6} }, i, j, s = 0; // 最后一个没有赋值的为 0 | |
for (i = 1; i < 3; i++) | |
{ | |
for (j = 0; j <= i; j++) | |
{ | |
s += a[i][j]; //a[2][2] = 0 | |
} | |
} | |
printf("%d\n", s++); | |
return 0; | |
} | |
/* | |
输出: 18 | |
*/ |
# 表达式等级类型
基本类型字符串
从低到高
如下,运算的时候,从低转到高
,表达式的类型
会自动提升为参与表达式求值
的最上级类
。
char
int
long
float
double
# 字符串操作
字符串时字符数组的一种形式,它以 "\0" 结尾
strcpy()
: 复制字符串strcmp()
: 比较字符串strlen()
: 计算字符串的长度
,遇到\0时
结束计算
,不算\0
, 且从1
开始计数。
// 将字符串 source 拷贝到字符串 destination 中 | |
// 函数返回 destination 字符串 | |
strcpy(char destination[], const char source[]); | |
// 将字符串 source 中前 numchars 个字符拷贝到字符串 destination 中 | |
// 注意 source 中 numchars 个字符将覆盖掉字符串 destination 中前 numchars 个字符 | |
// 函数返回 destination | |
strncpy(char destination[], const char source[], int numchars); | |
// 将字符串 source 接到字符串 target 的后面,要提前确保 taeget 有足够的空间 | |
// 函数返回 target | |
strcat(char target[], const char source[]); | |
// 将字符串 source 的前 nnumchars 个字符接到字符串 target 的后面 | |
strncat(char target[], const char source[], int numchars); | |
// 比较 first 是否大于 second,成功大于 0, | |
int strcmp(const char firststring[], const char secondstring); | |
// 统计长度 | |
// 统计字符串 string 中字符的个数 | |
strlen( const char string[]); |
# 参考资料
- C++ 继承
- typedef
- C 语言字符串操作总结大全