🥥
type
status
date
slug
summary
tags
category
icon
password
Property
类通过一个或几个特殊的成员函数来控制其对象的初始化操作,这些函数被称作构造函数(constructor)。构造函数的任务是初始化类对象的数据成员,类对象被创建的时候,编译系统对象分配内存空间,并自动调用该构造函数,由构造函数完成成员的初始化工作。
构造函数的名字和类名相同,和其他函数不一样的是,构造函数没有返回类型,且不能被声明为
const
函数。当创建类的一个const
对象时,直到构造函数完成初始化过程,对象才能真正取得其“常量”属性。因此,构造函数在const
对象的构造过程中可以向其写值。合成的默认构造函数
类通过默认构造函数(default constructor) 来控制默认初始化过程,默认构造函数无须任何实参。
如果类没有显式地定义构造函数,则编译器会为类隐式地定义一个默认构造函数,该构造函数也被称为合成的默认构造函数(synthesized default constructor)。对于大多数类来说,合成的默认构造函数初始化数据成员的规则如下:
- 如果存在类内初始值,则用它来初始化成员
- 否则默认初始化该成员
🥥
type
status
date
slug
summary
tags
category
icon
password
Property
除了定义类的对象如何初始化之外,类还需要控制拷贝、赋值和销毁对象时发生的行为
- 对象在初始化变量以及以值的方式传递或返回一个对象等情况下会被拷贝
- 当使用赋值运算符时会发生对象的赋值操作
- 当对象不再存在时执行销毁的操作,比如一个局部对象会在创建它的块结束时被销毁,当
vector
对象(或数组)销毁时存储在其中的对象也会被销毁
默认情况下,
C++
编译器至少会给一个类添加3个函数。- 默认构造函数(无参,函数体为空) )
- 默认析构函数(无参,函数体为空) )
- 默认拷贝构造函数,对属性进行值拷贝
🥥
type
status
date
slug
summary
tags
category
icon
password
Property
使用访问说明符(access specifier) 可以加强类的封装性:
- 定义在
public
说明符之后的成员在整个程序内都可以被访问,public
成员定义类的接口
- 定义在
private
说明符之后的成员可以被类的成员函数访问,但是不能被使用该类的代码访问,private
部分封装(隐藏)了类的实现细节
定义
Sales_data
类的新形式如下所示:作为接口的一部分,构造函数和部分成员函数(
isbn
和combine
) 紧跟在public
说明符之后,而数据成员和作为实现部分的函数则跟在private
说明符后面一个类可以包含零或多个访问说明符,而且对于某个访问说明符能出现多少次也没有严格限定。每个访问说明符指定了接下来的成员的访问级别,其有效范围到出现下一个访问说明符或类的结尾处为止。
class 或struct 关键字
🥥
type
status
date
slug
summary
tags
category
icon
password
Property
希望能修改类的某个数据成员。即使在一个
const
成员函数内,可以通过在变量声明中加入mutable
关键词做到。可变数据成员永远不会是
const
,即使是cosnt
对象的成员。因此一个const
成员函数可以改变一个可变成员的值。如:尽管
foo
是一个const
成员函数,它仍然能改变a
的值。该成员是个可变成员,因此任何成员函数,包括const
函数在内都能改变它的值。const
对象里除了mutable
,类型前都要自带const
属性,所以返回值如果是引用就必须加const
。🥥
type
status
date
slug
summary
tags
category
icon
password
Property
目录
类可以允许其他类或函数访问它的非公有成员,方法是使用关键字
friend
将其他类或函数声明为它的友元(friend)。友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。
友元函数
友元函数可以访问这个类中的私有成员:
友元声明只能出现在类定义的内部,具体位置不限。友元不是类的成员,也不受它所在区域访问级别的约束。通常情况下,最好在类定义开始或结束前的位置集中声明友元。
友元声明仅仅指定了访问权限,而并非一个通常意义上的函数声明。如果希望类的用户能调用某个友元函数,就必须在友元声明之外再专门对函数进行一次声明(部分编译器没有该限制)。许多编译器并未强制限定友元函数必须在使用之前在类的外部声明。一些编译器允许在尚无友元函数的初始声明的情况下就调用它,不过即使编译器支持,最好还是提供一个独立的函数声明。
🥥
type
status
date
slug
summary
tags
category
icon
password
Property
每个类都会定义它自己的作用域。在类的作用域之外, 普通的数据和函数成员只能由对象、引用或者指针使用成员访问运算符来访问。对于类类型成员则使用作用域运算符访问。不论哪种情况, 跟在运算符之后的名字都必须是对应类的成员:
作用域和定义在类外部的成员
一个类就是一个作用域的事实能够很好地解释为什么在类的外部定义成员函数时必须同时提供类名和函数名。在类的外部,成员的名字被隐藏起来了。
一旦遇到了类名,定义的剩余部分就在类的作用域之内了,这里的剩余部分包括参数列表和函数体。结果就是,可以直接使用类的其他成员而无须再次授权了。
例如,
Window_mgr
类的clear
成员,该函数的参数用到了window_mgr
类定义的一种类型:因为编译器在处理参数列表之前已经明确了当前正位于
Window_mgr
类的作用域中,所以不必再专门说明ScreenIndex
是Window _mgr
类定义的。出于同样的原因,编译器也能知道函数体中用到的screens
也是在 Window_mgr
类中定义的。另一方面,函数的返回类型通常出现在函数名之前。因此当成员函数定义在类的外部时,返回类型中使用的名字都位于类的作用域之外。这时,返回类型必须指明它是哪个类的成员。例如,我们可能向
Window_mgr
类添加一个新的名为addScreen
的函数,它负责向显示器添加一个新的屏幕。这个成员的返回类型将是ScreenIndex
,用户可以通过它定位到指定的Screen
:🥥
type
status
date
slug
summary
tags
category
icon
password
Property
目录
有的时候类需要他的一些成员与类本身直接相关,而不是与类的各个对象保持关联。
声明为 static的类成员称为 类的静态成员。用 static修饰的 成员变量,称之为 静态成员变量;用 static修饰的 成员函数,称之为 静态成员函数。静态的成员变量一定要在类外进行初始化。
权限可以被缩小但不能被放大,静态成员函数不可以调用非静态成员函数,非静态成员函数可以调用类的静态成员函数。
声明静态成员
使用关键字
static
可以声明类的静态成员,可以是public
或private
的。静态数据成员的类型可以是常量、引用、指针、类类型等。🥥
type
status
date
slug
summary
tags
category
icon
password
Property
目录
枚举(enumerations)可以将整数常量集合起来管理。与类一样,每个枚举定义一个新的类型。类是字面类型(literal types)。
C++
支持两个枚举:带作用域的(scoped)和无作用域的(unscoped),新标准引入了带作用域的枚举(scoped enumerations)。定义带作用域的枚举使用
enum class
或者enum struct
关键字,后面跟着枚举名字和逗号分隔的一系列枚举值:如果省略掉
class
或struct
关键字就是无作用域枚举,在无作用域enum
中,枚举名字是可选的:🥥
type
status
date
slug
summary
tags
category
icon
password
Property
目录
联合(
union
)是一种特殊类型的类。一个
union
可以有多个数据成员,但是在任意时刻只有一个数据成员可以有值。当给union
的某个成员赋值之后,该union
的其它成员就变成未定义的状态了。分配给一个union
对象的存储空间至少要能容纳它的最大的数据成员。union
需要的内存大小由最大的数据成员决定,内存大小将足够容纳这个数据类型。类的某些特性对
union
同样适用,但并非所有特性都如此:union
不能含有引用类型的成员,union
的成员可以是绝大多数类型。在C++11
标准中,含有构造函数或析构函数的类类型也可以作为union
的成员类型
union
可以为其成员指定public
、protected
、private
等标记。默认情况下union
的成员都是公有的
union
可以定义包括构造函数和析构函数在内的成员函数。但是由于union
既不能继承自其它类,也不能作为基类使用,所以在union
中不能含有虚函数