定义
关键字
C++中类的关键字为class,使用方法与C语言中的struct类似
类体中内容称为类的成员:类中的变量称为类的属性或成员变量,类中的函数称为类的⽅法或成员函数(定义在类面的成员函数默认为inline)
与struct不同的是,类中可以定义成员函数,而在C语言中struct只能定义变量而不能定义函数
但在C++中struct也升级为了class的用法,不过为了区别,通常使用class作为关键字
class Student
{
//成员函数
public:
void print()
{
cout << name << " " << number << " " << age << endl;
}
//成员变量
private:
string name;
int number;
int age;
};//此处存在分号
访问限定符
C++为了保证封装的稳定性,把类中的成员分成了三种访问权限
public修饰的成员在类外可以直接被访问
protected和private修饰的成员在类外不能直接被访问
访问权限作用域从该访问限定符出现的位置开始直到下⼀个访问限定符出现时为止,如果后面没有 访问限定符,作用域就到}(即类结束的位置)
当class的成员没有被访问限定符修饰时,默认为private权限,而struct中默认为public
一般的成员变量会被修饰成protected或private,需要类外使用的成员函数会修饰成public
类域
类定义了一个新的作用域,类的所有成员都在类的作用域中,如果想要在类外定义成员函数,就需要在函数名前面加上::并同时指明为哪个类域的函数
类域会影响编译的查找规则,如果没有::表明该函数来自哪个类域,编译器就会默认它为全局函数,而无法查找到相关的变量进行输出,加上类名::后编译器在查找函数声明时就会从对应的类域中查找,从而编译成功
class Student
{
//成员函数
public:
void print();
//成员变量
private:
string name;
int number;
int age;
};//此处存在分号
//若没有加上::表明来自哪个类域,就会编译失败
void print()
{
cout << name << " " << number << " " << age << endl;
}
//正确写法
void Student::print()
{
cout << name << " " << number << " " << age << endl;
}
实例化
概念
通过类类型在物理内存中创造对象的过程,被称作实例化输出对象
类是对象的抽象概念,限定了类中的成员变量有哪些,这些成员变量只是声明,并没有分配空间,
只有实例化时才会分配空间
一个类可以实例化出多个对象,只有实例化出的对象才会占用空间来储存成员变量
类定义和实例化对象的关系就像图纸和实物的关系,类定义为图纸,而实例化对象为实物
#include<iostream>
using namespace std;
//类定义(相当于图纸)
class Student
{
//成员函数
public:
void print()
{
cout << name << " " << number << " " << age << endl;
}
//成员变量
private://这里只是声明,并没有开辟空间
string name;
int number;
int age;
};//此处存在分号
int main()
{
Student st;//此处实例化对象st(相当于实物)
return 0;
}
所占空间大小
类中的元素被实例化后储存在对象中,而成员函数编译后只是一段命令,并没有被储存在对象中,而是使用时去调用命令
C++中,实例化对象也遵循内存对齐的规则(与struct相同)
内存对齐规则
1. 结构体的第⼀个成员对齐到和结构体变量起始位置偏移量为0的地址处
2.其他成员变量要对⻬到对⻬数的整数倍的地址处。
对⻬数=编译器默认的⼀个对⻬数与该成员变量大小的较小值
VS 中默认的值为8,Linux中gcc没有默认对⻬数,对⻬数就是成员⾃⾝的大小
3. 结构体总大小为最大对⻬数(结构体中每个成员变量都有⼀个对⻬数,所有对齐数中最大
的)的整数倍
4. 如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最⼤对齐数的整数倍处,结构体的整体大小就是所有最⼤对齐数(含嵌套结构体中成员的对齐数)的整数倍
下面我们举一个例子来具体说明(VS环境)
struct S1
{
char c1;
int i;
char c2;
};
int main()
{
printf("%d\n", sizeof(struct S1));
return 0;
}
上面的输出结果为:12
我们用一张图来说明为什么是12而不是6

首先我们的第一个成员c1是char型,占一个字节,第0位就是c1的位置
第二个成员i是int型,我们计算一下它的对齐数:int型占4个字节,VS对齐数默认为8,4<8,所以i的对齐数就是4,我们就需要对齐到偏移量为4的整数倍的地址(即4),所以4,5,6,7这四个字节放的就是i
第三个成员c2是char型,占一个字节,1<8,接下来我们就需要对齐到偏移量为1的整数倍的地址(即接下来的第8位)
所以三个成员存放的地方分别是:c1->0 i->4,5,6,7 c2->8
此时我们占了0-8的地址,一共9个字节,但是由于规则:结构体的大小为最大对齐数的整数倍
此时的对齐数分别是4和1,那就必须是4的倍数,2*4<9<3*4
所以该结构体所占的空间是12字节(1,2,3,9,10,11位置为空)
修改默认对齐数
#pragma 这个预处理指令,可以改变编译器的默认对⻬数
#pragma pack(1)
在VS中上面这个代码可以将默认的对齐数(8)改成1,下面的代码可以恢复默认
#pragma pack()
注意:更改后对结构体使用strlen时,数值有可能出现变化
下面的代码中,实例化了两个不同的类,它们的空间有所不同
#include<iostream>
using namespace std;
//定义非空类
class Student
{
//成员函数
public:
void print()
{
cout << number << " " << age << endl;
}
//成员变量
private://这里只是声明,并没有开辟空间
int number;
int age;
};//此处存在分号
//定义空类
class A
{
};
int main()
{
Student st;
A a;
cout << sizeof(st) << endl;
cout << sizeof(a) << endl;
return 0;
}

可以发现空类的空间大小为1,这是因为即使内容为空,也需要占位标识对象存在
this指针
假如存在两个类s1,s2时,s1调用某个类中函数时,函数怎么知道数据应该是s1还是s2?
类中函数在编译时,类的成员函数会默认在形参第一个位置增加一个当前类类型的指针,称为this指针,类中函数访问成员变量,本质都是通过this指针访问
C++中不能在实参和形参的位置写出this指针,但是可以在函数体内显示使用this指针
class Student
{
//成员函数
public:
void print()
{//函数内部可以明示使用this指针,也可以不写出来,默认使用的就是this指针
cout << this->name << " " << this->number << " " << age << endl;
}
//成员变量
private:
string name;
int number;
int age;
};//此处存在分号
(定义、实例化、this指针)&spm=1001.2101.3001.5002&articleId=144175209&d=1&t=3&u=6fff6aa2447d4daab76bb468a659d7e3)

被折叠的 条评论
为什么被折叠?



