类的特殊成员及三大特征
概述
- 三大特征包括:封装;继承;多态。
- 封装可以隐藏实现细节,使得代码模块化;
- 继承可以扩展已存在的模块,它们目的都是为了代码重用;
- 多态则是为了实现: 接口重用。
- C++的类中还包括三个三个特殊成员包括:const对象和const成员;静态(static)成员;友元。
特殊成员介绍
const对象和const成员
- 语法
class A{
mutable int x; //修饰符,允许const函数修改
const int num; //const成员变量
public:
A(int n):num(n){
....;} //初始化参数列表
void show(){
.....} //普通成员函数
void show()const{
.....} //const成员函数
};
A a;
const A b;//const对象
- 应用
①:const函数可以和同名的普通函数构成重载,非const对象优先调用非const函数,如果没有非const函数,再去调用const函数;
②:const对象只能调用 const函数,不能调用非const函数
③:const成员函数只能读取成员变量,不能修改成员变量,如果一定要修改,需要在声明成员变量时加mutable修饰。
静态(static)成员
- 概念:
分为静态成员变量和静态成员函数。
①:静态成员变量:在声明时加static,必须初始化,且要在类外进行初始化。默认初始化为0,类类型调用默认的构造函数。
②:静态成员函数:在声明时加static,静态成员函数只能访问静态成员,不能访问非静态成员。 - 语法:
class A{
public:
int x;
static int num; //静态成员变量
static void show(){
//静态成员函数
//只能访问静态成员
//x = 100; //错误
}
};
int A::num = 100; //类外初始化
int main()
{
cout<<A::num<<endl; //静态成员属于类,所有对象共用同一片内存
A::show; //通过类名调用,但是用对象调用也不报错
return 0;
}
- 注意:
静态成员不需要通过对象访问,可以直接通过类名访问,静态成员属于类,而不属于某个对象。静态函数中没有this指针。静态成员具有以上性质的原因是它们存放在独立的内存中。
友元
-
概念:
①:友元的作用就是让类外的数据突破访问权限的设置,友元可以访问类内任意数据;
②:可以将类/函数声明为某个类的友元,这些类和函数就可以访问类中的数据。 -
语法
①:友元函数:友元函数是一个全局函数,在类内部可以将该函数声明为友元,这样这个全局函数就可以访问类内的数据。②:友元类:如果将类A声明为类B的友元,类A中就可以随问类B中的数据,不受访问属性的限制。
//友元函数:在类内部声明:
friend 函数声明;
//友元类:在类内部声明:
friend class 类名;
- 注意:
友元不受访问属性的限制,可以在类外访问类中的所有数据,破坏了累的封装属性,如非必要,不要使用。
三大特征
封装
- 概念:
①:该隐藏的数据私有化,该公开的公有化(接口)(private、public);
②:目的就是为了分工合作,有助于使用的方便和安全性;
③:防止不必要的扩展。
继承
-
概念:
实现代码和数据的复用,复用的实现在已有的代码和数据的基础上扩展。
例如:“狗”继承了“动物”这个类的一些特征,又拓展了独有的特征。 -
继承的方式及语法:
①公有继承 ----------- class B:public A{…};父类的公有数据在子类中仍然公开
父类的受保护数据在子类中仍然受保护
父类的私有数据在子类中是隐藏的②保护继承 ----------- class B:protected A{…};
父类的公有数据在子类中变为受保护
父类的受保护数据在子类中仍然受保护
父类的私有数据在子类中是隐藏的③私有继承 ----------- class B:private A{…};
父类的公有数据在子类中变为私有
父类的受保护数据在子类中变为私有
父类的私有数据在子类中是隐藏的 -
注意:
①:父类中的成员在子类中的访问权限只会收缩,不会扩大,在子类中的访问属性不会超过继承方式。②:所谓的继承方式就是能够提供给子类的最大访问权限,实际权限小于等于继承方式,私有的数据必然在子类中隐藏
继承中的构造函数和析构函数问题
①:构造子类时,自动调用父类的构造函数;析构子类时,自动调用父类的析构函数。
②:调用构造和析构的顺序是相反的,先构造父类在构造子类,先析构子类,再析构父类。
③:在继承中,父类的数据由父类构造和析构,子类新增的数据由子类构造和析构。
④:如果父类中有多个构造函数(构造函数有参数),子类默认只会去调用无参的构造函数,可以在子类构造函数的初始化参数列表中里选择对应的父类构造函数。(语法参照下面)
class A{
int a;
int b;