类和对象的进阶
全局变量和局部变量
变量 | 初始化 |
---|---|
全局变量 | 在声明变量时没有进行初始化,则系统自动初始化为 0 |
局部变量 | 在声明变量时没有进行初始化,则系统自动初始化为 随机值 |
静态变量
使用 static
声明静态变量,根据定义的位置不同,分为:静态全局变量 和 静态局部变量 。
静态变量均存储在 全局数据区 。
静态变量只执行一次初始化,如果程序没有给出初始值,则相当于初始化为 0 。
静态局部变量 具有 局部作用域,但却具有 全局生存期 。
常量
定义常量的方式:
- 使用
#define
预处理器; - 使用
const
关键字。
// 常量
#define 常量名 常量值;
const 类型 常量名 = 常量值;
// 常函数
类型 函数名 (参数表) const;
构造函数
构造函数的作用
用于对对象进行初始化,实际上用来为成员变量赋值。
给出类定义时,如果没有编写类的任何构造函数,如系统会 自动 添加一个不带参数的构造函数。
构造函数的定义
构造函数的函数名与类名 相同,没有返回值。
一个类的构造函数可以有多个,即 构造函数允许重载。
定义类的对象 时,会自动调用类的构造函数。
构造函数的声明格式如下:
类名::类名(形参列表): 成员变量1(形参1), 成员变量2(形参2)
{
成员变量3 = 形参3;
}
构造函数的使用
创建类的任何对象时都一定会调用 构造函数 进行初始化。
对象需要占据内存空间,生成对象时,为对象分配的这段内存空间的初始化由构造函数完成。
如果程序中声明了 对象数组,则数组的每个元素都是一个对象,则一定要为对象所属的这个类定义一个 无参数的构造函数。
复制构造函数
复制构造函数时构造函数的一种,也称为 拷贝构造函数。它的作用时用一个 已存在的对象 去初始化另一个 正在创建的对象。
复制构造函数 只有一个参数,参数类型是 本类的引用。
参数为 const
引用:类名::类名(const & 类名);
参数为非 const
引用:类名::类名(& 类名);
自动调用复制构造函数的3种情况:
- 当用一个对象去初始化另一个对象,例如:
类名 对象名2(对象名1); 类名 对象名2 = 对象名1;
- 如果函数F的参数是类A的对象,当调用F时,会调用类A的复制构造函数。换句话说,作为形参的对象,是用复制构造函数初始化的,而且调用复制构造函数是的参数,就是调用函数时所给的参数。
- 如果函数的返回值时类A的对象,那么当函数返回时,会调用类A的复制构造函数。也就是说,作为函数返回值的对象是用复制构造函数初始化的,而调用复制构造函数是的实参,就是
return
语句返回的对象。
注意,在复制构造函数的参数表种,加上 const
是更好的做法。这样负责构造函数才能接收常量对象作为参数。
析构函数
与构造函数一样,析构函数也是成员函数的一种。它的名字也与类名相同,但要在类名前面加一个 ~
字符,以区别于构造函数。
析构函数没有参数,也 没有返回值。
一个类中 有且仅有一个析构函数。
如果程序种没有定义析构函数,则编译器 自动生成 默认的析构函数。
在 对象消亡 时,自动调用析构函数。
析构函数的作用:做一些善后处理的工作。例如:在创建对象时使用 new
运算符动态分配了内存空间,则在析构函数中应该使用 delete
释放掉内存空间。
类的静态成员
类的静态成员由两种:静态成员变量 和 静态成员函数 。在类体内定义类的成员时,在前面添加 static 关键字后,该成员即称为静态成员。
类的静态成员被类的所有对象 共享 。
类的静态不能是 虚函数 。
定义类静态成员变量时,在 类体中声明 静态成员变量,然后必须在 类体外定义 静态成员变量的初值。
静态成员变量的赋初值的格式如下:
类型 类名::静态成员变量 = 初始值;
在定义静态成员变量时,不需要使用
static
关键字。以免和一般的静态变量混淆。
访问类静态成员的格式:
类名::静态成员变量;
对象名.静态成员变量;
对象指针->静态成员变量;
类的静态成员函数没有 this
指针 ,不能在静态成员函数内访问非静态成员 。
类的常量成员
由关键字 const
修饰的类成员变量称为类的常量成员变量。
在对象被创建以后,其常量成员变量的值就不允许修改,只可以读取其值。
常量对象只能调用常量函数。
类的常量成员变量 必须 进行初始化,而且只能通过 构造函数 的 初始化列表 的方式进行。
常量成员变量的定义:
类名::类名(参数列表): 常量成员变量(参数) {}
常量成员函数的定义:
类型 类名::函数名(参数列表) const
{
函数体
}
成员对象和封闭类
一个类的成员变量如果是另一个类的对象,则该成员变量称为 成员对象 。
包含成员对象的类叫做 封闭类 。
在定义封闭类的构造函数时,需要添加 初始化列表 ,指明要调用成员对象的哪个构造函数。格式如下:
封闭类名::封闭类名(参数列表): 成员对象1(参数列表)
{
函数体
}
先调用成员对象的构造函数,再调用封闭类对象的构造函数。调用顺序与 声明顺序 有关,与初始化列表无关。
友元
友元的概念破坏了类的封装性和信息隐藏,但有助于数据共享,能够提高程序执行的效率。
友元使用 friend
关键字标识。
友元函数
在友元函数内部可以直接访问本类对象的私有成员。
将 全局函数 声明为类的友元函数,格式如下:
friend 类型 函数名(参数表);
将 类A的成员函数 声明为类的友元函数,格式如下:
friend 类型 类A::类A的成员函数名(参数表);
不能把其他类的 私有成员函数 声明为友元函数。
友元函数 不是 类的成员函数,但允许访问类中的 所有成员 。
在函数体中访问对象成员时,必须使用 对象名.对象成员名
的方式。
友元类
如果将一个类B声明为另一个类A的友元类,则类B中的所有函数都是类A的友元函数,在类B的所有成员函数都可以访问类A中的所有成员。
声明友元类的格式:
friend class 类名;
友元类的关系是 单向 的,不可传递 的。