行业知识
【C++】类和对象(上)
目录
- 一、面向过程和面向对象初步认识
- 二、类的引入
- 三、类的定义
- 四、类的访问限定符及封装
- 4.1 访问限定符
- 4.2 封装
- 五、类的作用域
- 六、类的实例化
- 七、类对象模型
- 7.1 如何计算类对象的大小
- 7.2 类对象的存储方式猜测
- 7.3 结构体内存对齐规则
- 八、this指针
- 8.1 this指针的引出
- 8.2 this指针的特性
- ���尾
一、面向过程和面向对象初步认识
C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。
C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。(基于面向对象是既可以是面向过程也可以是面向对象,因为C++兼容C语言)
二、类的引入
C语言结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数。比如:之前在数据结构中,用C语言方式实现的栈,结构体中只能定义变量;现在以C++方式实现,会发现struct中也可以定义函数。
#includeusing namespace std;// C语言写法struct Stack{// 成员变量int* a;int top;int capacity;};void StackInit(Stack st){// ...}void StackPush(Stack st , int x){// ...}// C++ 写法struct Stack{// 成员变量int* a;int top;int capacity;// 成员函数void Init(){// ...}void Push(int x){// ...}};在上面简易的栈中,我们可以看出C语言中的结构体在C++中升级为了类,使用起来比C语言更加的方便。上面定义类的struct可以替换为class,并且在C++中更习惯使用class,struct和class的区别只在于访问限定符,后面会讲到。
三、类的定义
class className{// 类体:由成员函数和成员变量组成}; // 一定要注意后面的分号class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。
类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数。
类的两种定义方式:
- 声明和定义全部放在类体中,需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。
struct Stack{public:// 成员函数void Init(){a = nullptr;top = capacity = 0;}void Push(int x){int newcapacity = capacity == 0 ? 4 : 2 * capacity;if (top == capacity){a = (int*)realloc(a, newcapacity);a[top++] = x;}}void Destroy(){free(a);a = nullptr;top = capacity = 0;}private:// 成员变量int* a;int top;int capacity;};- 类声明放在.h文件中,成员函数定义放在.cpp文件中,注意:成员函数名前需要加类名::
// .h 文件struct Stack{public:// 成员函数void Init();void Push(int x);void Destroy();private:// 成员变量int* a;int top;int capacity;};// .cpp 文件 #include"ClassAndObject.h"void Stack::Init(){a = nullptr;top = capacity = 0;}void Stack::Push(int x){int newcapacity = capacity == 0 ? 4 : 2 * capacity;if (top == capacity){a = (int*)realloc(a, newcapacity);a[top++] = x;}}void Stack::Destroy(){free(a);a = nullptr;top = capacity = 0;}一般情况下,更期望采用第二种方式。
成员变量命名规则的建议:
class Date{public:// 这里的函数不能区分是成员变量还是局部变量void Init(int year, int month, int day){year = year;// ...}private:int year;int month;int day;};// 针对上面情况可以对成员变量做一些修饰 // 并不一定要跟下面的方式相同,合理即可class Date{public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}private:int _year;int _month;int _day;};四、类的访问限定符及封装
4.1 访问限定符
C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用
struct Stack{public:// 成员函数void Init(){a = nullptr;top = capacity = 0;}void Push(int x){int newcapacity = capacity == 0 ? 4 : 2 * capacity;if (top == capacity){a = (int*)realloc(a, newcapacity);a[top++] = x;}}void Destroy(){free(a);a = nullptr;top = capacity = 0;}private:// 成员变量int* a;int top;int capacity;};【访问限定符说明】
- public修饰的成员在类外可以直接被访问
- protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
- 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
- 如果后面没有访问限定符,作用域就到 } 即类结束。
- class的默认访问权限为private,struct为public(因为struct要兼容C)
注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别
【面试题】
问题:C++中struct和class的区别是什么?
解答:C++需要兼容C语言,所以C++中struct可以当成结构体使用。另外C++中struct还可以用来定义类。和class定义类是一样的,区别是struct定义的类默认访问权限是public,class定义的类默认访问权限是private。注意:在继承和模板参数列表位置,struct和class也有区别,后序给大家介绍。
4.2 封装
面向对象的三大特性:封装、继承、多态。
在类和对象阶段,主要是研究类的封装特性,那什么是封装呢?
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
封装本质上是一种管理,让用户更方便使用类。
在C++语言中实现封装,可以通过类将数据以及操作数据的方法进行有机结合,通过访问权限来隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用。
五、类的作用域
类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员时,需要使用 ::作用域操作符指明成员属于哪个类域。
在C++中,出现一对{},那么就出现一个新的作用域。
class date{public:void init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print();private:int _year;int _month;int _day;};void date::Print(){cout public:void init(int year, int month, int day){_year = year;_month = month;_day = day;}public:int _year;int _month;int _day;};int main(){// date::_year; 错误,类中的成员变量只是声明// date._year; 错误,语法错误date d; // 实例化d._year;return 0;}public:void init(char* name, char* gender, int age){_name = name;_gender = gender;_age = age;}void SetPersonInfo(){// ...}void PrintPersonInfo(){// ...}public:char* _name;char* _gender;int _age;};int main(){Person p1;cout void PrintA(){// ...}private:int a;};// 仅有成员函数class B{void PrintB(){//...}};// 空类class C{};int main(){cout int a = 1;return *(char*)&a;}int main(){if (check_sys()== 1)printf("小端\n"); elseprintf("大端\n"); return 0;}public:void init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout date d1;date d2;d1.init(2023, 6, 6);d2.init(2023, 8, 8);d1.Print();d2.Print();return 0;}public:// 编译器自动转换// void init(dete* this , int year, int month, int day)void init(int year, int month, int day){_year = year;_month = month;_day = day;}public:int _year;int _month;int _day;};date d1;d1.init(2023, 6, 6);// 编译器自动转换// d1.init(&d1 , 2023, 6, 6);// 注意,传参时用户不能将&d1作为参数传给函数return 0;}public:void Print(){cout A* p = nullptr;p-Print();return 0;}public:void Print(){cout A* p = nullptr;(*p).Print();return 0;}public:void PrintA(){cout A* p = nullptr;p-PrintA();return 0;}
上一篇:怎么访问手机qq农场服务器?
下一篇:lls服务器怎么建设?