C++复习类与对象
struct和class的区别:
在C++中struct和class的区别只有两点。
1.struct的默认限定符为public,而class为private。
2.struct可以使用{…}进行初始化,而class不可以。(class在C++11标准支持初始化列表进行初始化)
class如果使用默认限定符,在用{…}进行初始化时,必须使用初始列表进行初始化,且C++98不支持{…},C++11支持。
C++中的struct和C中的struct的区别:
1.C中的struct不支持private/protected/public限定符。
2.C中的struct中不可以有成员函数。
C++中对象的创建:
1.类名 对象1; 调用默认构造函数
2.对象2 = 对象1; 调用复制构造函数
3.类名 对象3(对象1); 调用复制构造函数,使用 (对象) 进行初始化,相比C这是C++的初始化新增语法。
4.类名* 对象4指针 = new 类名 调用默认构造函数,new的对象存储在堆上,对象4指针在栈上。
this指针:
1.每个类都会自动生成一个(仅且一个),它是一个自动隐藏的私有成员。
2.当一个对象被创建时,this指针指向这个对象数据的首地址。
3.它不是对象的一部分,因此使用sizeof(this),并不会对结果产生影响。
构造函数:
1.在对象创建的时候自动执行。
2.构造函数与类名相同,没有返回值,也没有返回值类型。
3.可以有多个构造函数。
4.类中如果自己没有写构造函数,编译器会自动生成一个默认构造函数。
调用的时机:
1.对象直接定义时。
2.new动态创建时。
构造函数不可以显式的被调用。
构造函数的三个作用:
1.给创建的对象建立一个标识。
2.为对象数据成员开辟内存空间。
3.完成对象的数据成员的初始化。
类名(参数):成员变量(参数){
函数体
}
作用:初始化非静态成员变量
- 说明 从概念上来讲,构造函数的执行可以分成两个阶段,初始化阶段和计算阶段,初始化阶段先于计算阶段。
- 必须使用初始化列表的情况
1.常量成员,因为常量只能初始化不能赋值,所以必须放在初始化列表里面。
2.引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以也要写在初始化列表里面。
3.没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化,而是直接调用拷贝构造函数初始化。 初始化列表与构造函数内部成员变量赋值的区别: 成员变量初始化与成员变量赋值
类名(参数):成员变量(参数){
函数体
}
作用:初始化非静态成员变量说明:从概念上来讲,构造函数的执行可以分成两个阶段,初始化阶段和计算阶段,初始化阶段先于计算阶段。
- 必须使用初始化列表的情况
1.常量成员,因为常量只能初始化不能赋值,所以必须放在初始化列表里面。
2.引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以也要写在初始化列表里面。
3.没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化,而是直接调用拷贝构造函数初始化。 - 初始化列表与构造函数内部成员变量赋值的区别 成员变量初始化与成员变量赋值
C++的函数可以有默认参数
语法:
1.默认参数必须写在函数声明中,不可出现在实现的参数列表中。
2.默认参数必须写在非默认参数后,且可以写任意多个。 用法:可以传值,或者选择不传。
析构函数
无返回值类型和返回值,且只有一个,如果没有自己写,会默认生成一个默认析构函数。
调用时机:对象离开作用域。使用delete。
作用:释放对象所占用的资源。
引用(别名)
声明:const 类型名& 对象名/ 类型名 const & 对象名
何处使用:1.函数参数列表。 2.成员变量,对象初始化时,必须显示初始化变量
为什么用引用:1.避免对象的复制。 2.避免传递空指针。 3.使用方便。
可以使用引用的类型:1.基本类型 2.复合类型 3.自定义类型
作用: 取代指针
本质:typen &name <->type* const name是引用的本质,引用是一个常量指针。
两者的区别是,如果使用m2这个函数,则需要我们人为的去取一次地址。如果使用m1这个函数我们传递参数时,无需为其取地址,编译器会自动为我们进行这一操作,然后将取得的地址传给了形参。因此我们使用引用时,不用考虑编译器是如何实现的,只有去分析语法时,才需要去考虑编译器为我们做了什么。
引用作为左值:
函数返回值为引用时,我们需要注意返回值的生存周期,如果返回值为栈变量,那么它不能成为其他引用的初始值,也不能作为左值来使用,若返回值为全局变量和静态变量则可以作为左值,也可以用来作为其他引用的初始值。
引用和指针的区别:
1.指针申请一块内存,它的内容是所指内存的地址; 引用是某一块内存的别名。
2.指针的值是可以更改的,而引用的值一旦初始化后不可更改。
3.引用不可为空,指针可以为空。
4.sizeof(指针)得到指针本身的大小,sizeof(引用)得到所指向变量/对象的大小。
引用通常使用在:成员变量和函数的参数列表。
拷贝/复制构造函数
调用时机:
一个对象作为函数参数,以值传递的方式传入函数体
一个对象作为函数返回值,以值从函数返回
一个对象用于给另外一个对象进行初始化(赋值初始化)
gcc会使用named return value优化,不执行拷贝构造函数,需要执行的话需要增加选项’-fno-elide-constructors’;
VS则会执行拷贝构造函数
默认拷贝构造函数
本质:内存拷贝
作用:复制一个已经存在的对象
禁用默认拷贝构造函数?在类定义,添加私有的复制构造函数,但不实现。
赋值运算符重载函数
固定的格式:
类名& operator=(const 类名& 形参) {
…
return *this;
}
调用时机:赋值
赋值运算符重载
1.判断是否自我赋值
2.释放之前资源
3.获取新资源
4.返回自身的引用
默认赋值运算符重载函数重载本质:内存拷贝
如何禁用默认赋值运算符重载函数?在类定义,添加私有的赋值运算符重载函数的声明,但不实现。
赋值操作符:当两个对象都已经存在
拷贝构造函数与赋值操作符的区别:
拷贝构造函数:当一个已经存在的对象来初始化一个未曾存在的对象
赋值操作符:当两个对象都已经存在
深拷贝与浅拷贝
浅拷贝:只实现拷贝指针地址
深拷贝:重新分配堆内存,拷贝指针指向的内容.
要实现深拷贝,必须实现拷贝构造函数,赋值运算符重载,析枸函数。
赋值运算符重载
1.判断是否自我赋值
2.释放之前资源
3.获取新资源
4.返回自身的引用
友元:
作用:非成员函数访问类中的私有成员
分类:
1.全局友元函数:将全局函数声明为友元函数
2.友元成员函数:类的提前引用声明,将一个函数声明为多个类的友元函数
3.友元类:将整个类声明为友元
特点:友元单向,不可传递。
const:
本质:不可修改
const 类型 变量 = 初始值;
const 类型 对象;
定义时必须初始化
全局作用域声明的const变量默认作用域是定义所在文件
const对象只能调用const成员函数
const与宏定义#define的区别
const | 宏定义#define |
---|---|
编译器处理方式 | 编译运行阶段使用 |
类型 | 有具体的类型 |
安全检查 | 编译阶段会执行类型检查 |
存储方式 | 分配内存 |
用法:
|1|const
指针|类型* const 变量 = 初始值;
|指针指向地址不能改变|
|2|指向const
对象的指针|const 类型* 变量 = 初始值;
类型 const* 变量 = 初始值;
|指针指向对象不能改变|
|3|指向const
对象的const
指针|const 类型* const 变量 = 初始值;
|指针指向地址和对象不能改变|
const与引用
类型 const& 变量 = 初始值;
const与函数的参数和返回值:
类型 | 语法 | 作用 | 说明 |
---|---|---|---|
const 参数 | 返回值类型 函数(const 类型 形参) | 函数内部不能改变参数的值 | 这样的参数的输入值 |
const 返回值 | const 返回值类型 函数(形参列表) | 函数的返回值不能改变 | 常用于字符串/指针 |
const成员变量
不能在类声明中初始化const数据成员。
const成员变量只在构造函数的初始化列表中初始化。
const成员变量不能使用赋值运算符重载函数。
const成员函数
成员函数不能修改类中任何成员变量。一般在函数的最后进行修饰,且声明和定义必须加上const。
const修饰位置 | 作用 |
---|---|
变量 | 变量不可修改,通常用来替代#define |
对象/实例 | 对象的成员变量不可修改,只能调用const 成员函数 |
函数参数 | 参数不能在函数内部修改,只作为入参 |
函数返回值 | 返回的结果不能被修改,常用于字符串 |
成员变量 | 只能在初始化列表中初始化 |
成员函数 | 不改变成员变量 |
static限定符
生存周期:整个生存周期
作用域:属于类,不属于对象。
static只能用于类的声明中,定义不可为static。
非静态可以访问静态的函数
静态成员可以设置访问权限
禁忌:
静态成员函数不能访问非静态函数或变量
静态成员函数不可以使用this关键字
静态成语函数不可以使用cv限定符
因为静态成员函数属于类而不是某个对象
静态成员变量
语法:
在类定义中声明,但在类实现中初始化。
在声明时需要指定static,实现时则不需要static。
对象的大小不包含静态成员变量。
因为静态成员变量不属于对象而是属于一个类。静态成员变量所有的类的对象共享。
static 修饰位置 | 作用 |
---|---|
变量 | 静态变量 |
函数 | 只源文件内部使用的函数 |
成员变量 | 对象共享变量 |
成员函数 | 类提供的函数,或者作为静态成员对象的接口 |
const与static
变量类型 | 声明位置 |
---|---|
一般成员变量 | 在构造函数初始化列表中初始化 |
const 成员常量 | 必须在构造函数初始化列表中初始化 |
static 成员变量 | 必须在类外初始化 |
static const /const static 成员变量 | 变量声明处或者类外初始化 |
注意:
static const
/const static
在类定义中成员变量只能初始化整型数据。
慎用内联
如果函数体内的代码比较长,使用内联将导致内存消耗代价较高
如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大
不要随便地将构造函数和析构函数的定义体放在类声明中
运算符重载
1.成员函数运算符重载
2. 友元函数运算符重载
规则:
不能重载的运算符:成员运算符.
、作用域运算符::
、sizeof
、条件运算符?:
不允许用户自定义新的运算符,只能对已有的运算符进行重载
重载运算符不允许改变运算符原操作数的个数
重载运算符不能改变运算符的优先级
重载运算符函数不能有默认的参数,会导致参数个数不匹配
本质:函数重载