1、类的定义
class 类名{ //成员函数 //成员变量 };
class为定义的关键字,{ }内是类的主体,注意后面的 ; 不要忘了
类体中的内容成为类的成员,类中的变量为成员变量或类的属性,类中的函数为成员函数或类的方法,
类的两种定义方式:
1、声明和定义都放在类中, 需注意成员函数如果在类中定义,编译器可能会将其当成内联函数处理;
2、声明和定义分离,在头文件中声明,在源文件中定义,
一般情况下,都采用第二种方式;
2、成员变量的命名方式
成员变量和函数形参的名字注意区别,比如下面的代码:
class Date { public: void Init(int year) { // 这里的year到底是成员变量,还是函数形参? year = year; } private: int year; };
为了方便区分我们通常会做一些区别,让他们看起来有联系,又容易区分:
class Date { public: void Init(int year) { _year = year; } private: int _year; };
3、类的访问限定符
C++实现封装的方式:用类将对象的属性和方法绑定到一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
访问限定符说明:
1.public修饰的成员在类外可以直接被访问;
2. protected和private修饰的成员在类外不能直接被访问 (此处protected和private的作用是类似的);
3.访问权限的作用域从该访问限定符出现的位置开始,直到下一个访问限定符出现时为止;
4.如果后面没有访问限定符,作用域就到 } 即类结束为止;
5.class默认访问权限是private,struct默认是public(因为要兼容C)。
注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别。
问题:C++中class和struct的区别是什么?
C++中struct可以当作结构体来用,因为要兼容C,也可以定义类,和class定义类差不多,区别是struct定义的类默认是public,而class定义的类默认是private。注意:在继承和模板参数列表位置,struct和class也有区别,后序给大家介绍。
4、封装
面对对象的三大特性:封装,继承,多态。
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
在C++语言中实现封装,可以通过类将数据和操作数据的方法进行有机结合,通过访问权限来隐藏对象内部实现细节,控制哪些方法可以直接在类外部被使用访问。
5、类对象模型
如何计算类的大小?
class A { public: void PrintA() { cout<<_a<<endl; } private: char _a; };
和结构体差不多,类里面只计算成员变量的大小,而成员函数不占用类的空间,
所以一个类的大小,实际就是该类中“成员变量”之和,当然要注意内存对齐。
注意空类的大小,编译器给了空类一个字节来唯一标识这个类的对象(不同编译器对空类的处理可能不一样,这里用的编译器是vs2022)。
结构体内存对齐规则:
1. 第一个成员在与结构体偏移量为0的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
VS中默认的对齐数为8
3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整
体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
忘记的话可以复习前面的博客——浅谈结构体,
6、this指针
class Date { public: void Init(int year, int month, int day) { _year = year; _month = month; _day = day; } void Print() { cout <<_year<< "-" <<_month << "-"<< _day <<endl; } private: int _year; // 年 int _month; // 月 int _day; // 日 }; int main() { Date d1, d2; d1.Init(2022,1,11); d2.Init(2022, 1, 12); d1.Print(); d2.Print(); return 0; }
Date类中有Init与Print两个成员函数,函数体中没有关于不同对象的区分,那当d1调用Init函数时,该函数是如何知道应该设置d1对象,而不是设置d2对象呢?
C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏
的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量” 的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需来传递,编译器自动完成。
this指针的特性:
1. this指针的类型:类型* ,即成员函数中,不能给this指针赋值。
2. 只能在“成员函数”的内部使用
3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给 this形参。所以对象中不存储this指针。
4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传 递,不需要用户传递。
面试题:
1. this指针存在哪里?
栈区(形参一般存放在栈区)或者寄存器中。
2. this指针可以为空吗?
可以,但是不能对空指针解引用。