C++ 基础知识备忘
常用字符串函数
头文件
include<string.h>
1 | strlen() // 实际字符串长度,不包括'\0' |
函数重载定义
C++特性,因为C++编译后的名字是带参数类型,所以相同函数名,参数不同(类型,个数,顺序)
当心隐式类型转换导致重载函数产生二义性
1 | void output(int i) |
全局函数和成员函数重名时,并非重载,如果调用全局函数需要::funtion
成员函数的重载,覆盖和隐藏
重载和覆盖
成员函数重载特征
- 相同范围内(同一个类中)
- 函数名相同
- 参数不同
- virtual 可有可无
- 返回值可以不同
覆盖(override派生类覆盖基类)的特征
- 不同范围
- 函数名字相同
- 参数相同
- 基类必须有virtual
令人迷惑的隐藏
如果派生类函数名和基类相同,但参数不同,无论是否有virtual 基类都被隐藏。
如果派生类函数名和基类相同,参数也相同,基类没有virtual,基类被隐藏。
1 | class Base |
参数的缺省值
参数缺省只能出现在声明
如果有多个参数,参数只能从后往前按个缺省
运算符重载
两种实现方式
- 友元函数
- 类成员函数
1 | class Base { |
coredump问题调查
1 |
|
1 | xuqi@xuqi-VirtualBox:~$ g++ main.cpp |
字节序列
端序 | 内存案例(0x44332211) | 处理器家族 |
---|---|---|
大端(Big Endian) | 0x44 0x33 0x22 0x11 | SUN SPARC/IBM PowerPC |
小端(Little Endian) | 0x11 0x22 0x33 0x44 | Intel 80x86 系列 |
以unsigned int value = 0x12345678为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf[4]来表示value:
1 | 大端Big-Endian: 低地址存放高位,如下: |
大端小端没有谁优谁劣,各自优势便是对方劣势:
小端模式 :强制转换数据不需要调整字节内容,1、2、4字节的存储方式一样。
大端模式 :符号位的判定固定为第一个字节,容易判断正负。
MSB:MoST Significant Bit ——- 最高有效位
LSB:Least Significant Bit ——- 最低有效位
1 | bool IsBigEndian() |
Log输出格式化
1 |
|
①args…
第一个传给fmt, 第二个开始传给args…可为多个。
②##args
##args的意思,就是把args...中的多个参数,串连起来。
#fmt的话,就是把fmt传进来的内容以字符串形式输出
拷贝构造函数和赋值函数
1. 如果不写拷贝构造函数,编译器以位拷贝的方式,所以如果类中有指针变量,就会隐含错误。
隐含错误包括
原有的内存没有被释放,造成内存泄漏。
两个指针指向同一块内存,任何一方改动都会影响另一方。
对象析构,数据被释放了两次。
2. 拷贝构造函数和赋值函数的区别
1 | String a("hello"); |
3. 关键字explicit
可以禁止“单参数构造函数”被用于自动类型转换,没有explicit的话test s = 4;能编译通过
4. 派生函数应该是virtual 函数,否则派生类析构时,基类无法析构
5. 派生函数的赋值函数,需要对基类成员也做赋值
1 | Derived & Derived::operate =(const Derived &other) |
模板学习之typename
模板的声明可以使用关键字class代替typename进行,这两种声明方式没有任何的区别,其意义是完全一样的
1 | template<typename T> class Widget; // uses "typename" |
1 | template<class T> class Widget; // uses "typename" |
但是typename还有另外的使用方法
1 | template<typename C> // print 2nd element in |
如果C::const_iterator是一个类型,则定义了一个C::const_iterator类型的指针x,而如果C::const_iterator是类型C的一个成员变量呢,如果x正好是一个全局变量呢,这个表达式就是两个变量的乘积了。此处产生歧义的原因就在于C::iterator意义不明确,它依赖于模板参数,我们将其称为嵌套依赖名字(nested dependent name),为了消除歧义,C++规定,对于嵌套依赖名字,统统不解释为类型,除非显示声明。这就是为什么说上面那段代码有问题,因为编译器不认为C::const_iterator是一个类型。那么如何显示声明C::iterator为一个类型呢,就是使用typename关键字!
1 | template<typename C> // print 2nd element in |
C++11 模板中的 using
C++ 11 后的类型别名或者模板别名
类型别名是指:之前定义的类型的引用(类似 typedef)
模板别名是指:模板类的引用
1 | 例子: |