目录
类的三大特性
封装、继承、多态。
类的封装
class 类名
{
private : //私有的
public : //公有的
protected : //受保护的
//1.属性
//2.行为(即功能函数)
};
类的封装性 = 属性 + 行为 + 访问权限
访问权限
用来修饰类中属性或函数的访问级别的。
public :公有的,类中或类外对象均可直接访问。
private:私有的,只有类中可以访问,类外或子类之中均不可以访问。
protected:受保护的: 只有类中或子类的类中可以访问,类外是不可以访问的。
如果类外对象想要设置类中私的属性或方法,要使用一个公有的public权限下的接口访问。如自定义set()、get()方法。
使用class 来表示一个类,class在C++中表示这个类是默认的私有权限,而struct表示的类默认的是公有权限。
类的大小
class定义的类,也遵从C中的struct结构体的字节对齐原则。当如果是一个空类,编译器会对其进行优化,安插一个无符号字符整形。占一个字节。
类中的成员函数并不占有类或类对象的内存大小,所有类对象共享成员函数的入口地址。
构造/析构
构造
类名(形参列表)
{
//初始化类中属性的相关逻辑。
}
概念
1.构造时没有返回值,连void都没有,所以这个构造函数非给程序员手动调用的,他是由编译器在生成对象时,自动调用完成的
2.意义:就是定义对象,完成对类中属性的初始化操作的。
3.调用时机:定义对象时,无论是在堆上,或在栈上定义对象,将由编译自动完成调用于之参数相匹配的构造
4.编译器默认生成构造函数:当类中没有定义构造函数时,编译器将自动生成一个默认构造(无参构造)。如果类中程序员提供了任何一个构造函数,那么编译器将不再提供默认构造
5.构造函数也是函数,只不过是由编译器自动调用的函数,他也遵从函数重载的原则。
有参/无参构造
A()
{
cout << "A的无参空构造" << endl;
}
A(int a,int b)
{
cout << "A的多参构造" << endl;
}
显式/隐式调用
显式调用:
A a;
A a1(100);
隐式调用:
A a = 100;
explicit 关键字
explicit A(int a) //explicit就是用来告诉编译器必须显式调用才可以,不然报错。
{
this->a = a;
cout << "A的有参构造" << endl;
}
析构
~类名()
{
//书写,当类中有属性指针,指向堆区的情况时,资源的回收清理的逻辑。
}
概念
意义:用来清理类中有属性指针,指向堆区资源的情况,当类对象被销毁时,回收堆上资源。为了避免资源泄露
调用时机:当类对象被销毁时,自动先调用析构函数,完成对类中属性指针指向堆区资源的清理工作,然后再去销毁本类对象。
//堆上对象,由程序员手动完成销毁对象的操作(delete),销毁对象前自动先调用析构函数,完成对象中的有属性指针指向堆上的资源。
Stu* stu2 = new Stu("lisi",20);
delete stu2;
类中属性的初始化
C++中const修饰的变量,在定义时必须赋初值。
初始化列表
特点:
1.构造函数的初始化列表,也是由编译器自动调用的,但是他调用的时机在构造函数之前。 即在new之后,构造函数之前。
2.调用时机:在类开辟空间时,同时会被调用,就是告诉编译器按类中成员的声明顺序进行初始化。
3.每个成员变量在初始化列表中,只能初始化一次。
4.类中有特殊成员的初始化:const修饰的对象或变量、引用类型成员或变量,自定义类型指定调用构造函数时使用。
5.如果类中有比较大的结构体对象的初始化,可以在初始化列表中进行。
6.初始化列表顺序尽量保持与类中成员声明顺序相同。
例:
class Stu
{
private:
string _name;
int _age;
const int _id;
int* p;
A a;//没有默认构造的对象的初始化
public:
//此处使用构造函数的特殊语法:初始化列表进行初始化类中的属性:
Stu(string name, int age, int id):_name(name),_age(age),_id(id),p(new int[1024]),a(A(1))
{
cout << "Stu的构造" << endl;
}
};
static静态成员
回顾静态区:
当一个进程被加载时,系统会首先加载静态区数据,静态区的数据包括了:
1.文件代码段:编译好的机器码,内容即是一个个函数机器码及保存函数地址的指针。
2.rodata段:即全局只读数据,比如:全局const修饰的全局变量或常量字符串。
3.data段:已初始化的全局变量或static修饰且初始化的变量。
(data段数据将在程序执行前系统调用copy_data()函数向程序中拷贝一份副本)。
特点
1.static修饰的成员变量必须在类外进行初始化。
2.由于类中静态成员变量,是属于整个进程的,进程执行前就已经在静态区存在了。而类对象是生存在动态区的,所以此成员不依赖于某个类对象的,它是属于整个进程的。
因为他又隐藏于类中,所以可以使用类名+域名访问的形式直接访问。(不会有类内的访问权限的限制)
3.由于静态区数据只会由进程加载一次,在静态区的类成员数据,且此静态成员数据只有一分,是所有对象的共享部分。也就是所有对象都共享这份数据,当这份数据被修改时,所有对象中的这份共享部分都将被修改
4.由于静态成员变量定义在静态区,而对象是存在于动态区之中,所以静态成员变量并不占用类对象的内存空间。
5.所以当需要一个数据对象为整个类服务,而不是某一个对象服务时,同时又力求不破坏类的封装性,即可以把此成员隐藏在类的内部,对外不可见,同时又可以为每个本类对象共享,即可以把此属性升级的静态属性。
类中定义静态变量
...{
public:
static int count;
}...
类外初始化
数据类型 作用域(类域) :: 变量名 = 初值;
int Stu : : count = 0;
必须且只能在类外进行初始化,但可以在类中修改值。
当用static在类中修饰一个成员变量时,由于类中定义的static是隐藏在类中,系统无法调用bss_clear()直接进行初始化。
所以C++语法规定,当系统加载时,必须要在类外对static修饰的成员变量进行首次初始化。
如果没有在类外对static修饰的成员进行初始化,那么此变量在类中仅为一个声明,而没有定义。当对象引用这个成员变量时,就会发生连接出错误。
类的继承
传送门:C++类的继承关系_m0_58495729的博客-CSDN博客