类的定义、this指针
1.类
1.1 什么是类?
C语言结构体的升级,不但可以在集合中定义变量,而且可以定义函数。
1.2 类的定义:
class(类名)
{
(类体:成员变量和成员函数)
}; //后面一定要加上分号。
- 声明和定义都放在类体中定义:
class test
{
public:
void Print()
{
cout << a << endl;
}
private:
int a;
};
- 声明放在 .h中,定义放在 .cpp中:
class test
{
public:
void Print();
private:
int a;
};
#include"test.h"
void test::Print()
{
cout << a << endl;
}
1.3 类的访问限定符
访问限定符 | 作用 |
---|---|
public(公有) | 修饰的成员在类外可以直接被访问 |
protect(保护) | 修饰的成员在类外不能直接被访问 |
private(私有) | 修饰的成员在类外不能直接被访问 |
访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
class test
{
//下面为公有成员
public:
void Print()
{
cout << a << endl;
}
//下面为私有成员
private:
int a;
};
C++中class和struct都可以定义类,区别是class定义类时成员的默认访问方式是私有,struct定义类时成员的默认访问方式为公有。
1.4 类的作用域
类里面就是一个作用域,出了类想要定义成员就需要用 :: 作用域解析符来说明成员属于哪个类域里。
class test
{
public:
void Print();
private:
int a=0;
};
void test::Print() //Print这个函数属于test类域
{
cout << a << endl;
}
1.5 类的实例化
类只是一个模型,确定了他有哪些成员,在定义时并没有给他分配内存空间。
当类实例化时,实例化出的对象才会占用内存空间,一个类可以实例化出多个对象。
举个例子:
具体的实现过程如下:
class stu //定义stu类
{
public:
void Print();
public:
int _age;
char* _name;
char* _sex;
};
int main()
{
stu stu1; //stu类实例化出对象stu1
stu stu2; //stu类实例化出对象stu2
stu1._age = 20;
stu1._name = "张三";
stu1._sex = "男";
stu1._age = 18;
stu1._name = "李四";
stu1._sex = "男";
stu1.Print();
stu2.Print();
return 0;
}
1.6 类对象的大小怎样计算?
类实例化对象后,每个对象都有一份自己的成员变量,但是由于每个对象调用成员函数时,用的都是同一份代码,所以对象并没有自己独有的成员函数,而是类实例化出的所有对象共用一份成员函数。因此类的对象大小只需要考虑成员变量。
类实例化出的对象成员变量的大小计算方法与C语言中结构体大小的计算方法规则相同(内存对齐)。
内存对齐:
- 第一个成员变量在偏移量为0处;
- 其他成员变量要对齐到对齐数整数倍的偏移量处;
- 对象的总大小是最大对齐数的整数倍;
注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
class Stu
{
public:
void Print();
public:
char _name;
int _age;
char _sex;
};
int main()
{
Stu stu1;
cout << sizeof(stu1) << endl; //输出结果为12
return 0;
}
上述代码内存对齐的过程如下:
2.this指针
2.1 什么是this指针?
先来看一段代码:
class Date
{
public:
void Print();
void SetDate(int year,int month,int day);
private:
int _year;
int _month;
int _day;
};
void Date::Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
void Date::SetDate(int year,int month,int day)
{
_year = year;
_month = month;
_day = day;
}
int main()
{
Date d1;
Date d2;
d1.SetDate(2020, 2, 2);
d2.SetDate(2021, 3, 3);
d1.Print();
d2.Print();
return 0;
}
运行结果:
这里就引出了一个问题:执行SetDate()时,成员函数中并没有对不同对象的区分,那么为什么不同对象调用成员函数时,函数可以将传进来的参数准确的赋值给对应对象的成员变量?
C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象,在函数体中对成员函数的操作都是通过这个指针,即操作的是当前对象的成员函数。
我们通过汇编观察上述代码中SetDate()的执行过程:
简单地可以这样理解:
以上这些工作都是编译器帮我们完成的。
2.2 this指针的特性
- 在对象调用成员函数时,编译器会将该对象的地址作为实参传递给this形参,并不存在于对象中;
- this指针是成员函数的一个隐含形参,由编译器通过ecx寄存器传递,不需要用户操作;
- this指针的类型为 类类型* const;