当前位置: 首页 > news >正文

福州网站建设公司大悟网站建设

福州网站建设公司,大悟网站建设,重庆建设工程交易网,我的文档上传到网站 做链接类与对象#xff08;一#xff09;一、类的引入二、类的定义1、类的两种定义方式#xff1a;2、成员变量命名规则的建议#xff1a;三、类的访问限定符及封装1、访问限定符2、封装四、类的实例化1、类的实例化概念2、类对象的大小的计算五、this指针this指针的特性一、类的… 类与对象一一、类的引入二、类的定义1、类的两种定义方式2、成员变量命名规则的建议三、类的访问限定符及封装1、访问限定符2、封装四、类的实例化1、类的实例化概念2、类对象的大小的计算五、this指针this指针的特性一、类的引入 在C语言结构体中只能定义变量但是在C中结构体内不仅可以定义变量也可以定义函数。比如 #includeiostream #includestdlib.h using namespace std; typedef int DataType; struct Stack {void Init(int _capacity4)//缺省参数{DataType* tmp (DataType*)malloc(sizeof(DataType) * _capacity);if (nullptr tmp){perror(malloc fail:);exit(-1);}_a tmp;_Top 0;_capacity _capacity;}DataType* _a;int _Top;int _capacity; }; int main() {Stack s1; //C中struct定义的结构创建变量时不需要加structs1.Init(10);s1._Top 100;s1._capacity 200;return 0; }上面结构体的定义在C中更喜欢用class来代替struct。 二、类的定义 类的定义格式为 class className { // 类体由成员函数和成员变量组成 }; // 一定要注意后面的分号class为定义类的关键字ClassName为类的名字{}中为类的主体注意类定义结束时后面分号不能省略。 类体中内容称为类的成员类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数。 1、类的两种定义方式 声明和定义全部放在类体中如类的引入中的代码需注意成员函数如果在类中定义编译器可能会将其当成内联函数处理。类声明放在.h文件中成员函数定义放在.cpp文件中注意类定义了一个新的作用域类的所有成员都在类的作用域中。在类体外定义成员时需要使用 ::作用域操作符指明成员属于哪个类域因此成员函数名前需要加类名 ::一般情况下更期望采用此种方式。 头文件Test.h中 函数实现:Test.cpp中 主函数文件:2023.02.07.cpp中 2、成员变量命名规则的建议 先看一个错误示范 class Date {void Init(int year){// 这里的year到底是成员变量还是函数形参year year;}int year; };实际上 号两边都是形参因为局部变量优先这里我们可以看出命名的重要性,为了避免与形参混淆我们通常对成员变量前加一个_符号。 class Date {void Init(int year){_year year;}int _year; };三、类的访问限定符及封装 1、访问限定符 C实现封装的方式用类将对象的属性与方法结合在一块让对象更加完善通过访问权限选择性的将其接口提供给外部的用户使用。 访问限定符的使用 class Stack { public:void Init(int _capacity 4); private:DataType* _a;int _Top;int _capacity; };【访问限定符说明】 public修饰的成员在类外可以直接被访问protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止如果后面没有访问限定符作用域就到} 即类结束。class的默认访问权限为privatestruct为public(因为struct要兼容CC的struct是公有的) 注意访问限定符只在编译时有用当数据映射到内存后没有任何访问限定 #includeTest.h int main() {Stack s1;s1.Init(10);//编译成功s1._Top 100;//编译报错无法访问return 0; }【面试题】 问题C中struct和class的区别是什么 解答C需要兼容C语言所以C中struct可以当成结构体使用。另外C中struct还可以用来定义类。和class定义类是一样的区别是struct定义的类默认访问权限是publicclass定义的类默认访问权限是private。 注意在继承和模板参数列表位置struct和class也有区别后序给大家讲解。 2、封装 面向对象的三大特性封装、继承、多态。 在类和对象阶段主要是研究类的封装特性那什么是封装呢 封装将数据和操作数据的方法进行有机结合隐藏对象的属性和实现细节仅对外公开接口来和对象进行交互。 封装本质上是一种管理让用户更方便使用类。 例如对于电脑这样一个复杂的设备提供给用户的就只有开关机键、通过键盘输入显示器USB插孔等让用户和计算机进行交互完成日常事务。但实际上电脑真正工作的却是CPU、显卡、内存等一些硬件元件。 对于计算机使用者而言不用关心内部核心部件比如主板上线路是如何布局的CPU内部是如何设计的等用户只需要知道怎么开机、怎么通过键盘和鼠标与计算机进行交互即可。因此计算机厂商在出厂时在外部套上壳子将内部实现细节隐藏起来仅仅对外提供开关机、鼠标以及键盘插孔等让用户可以与计算机进行交互即可。 在C语言中实现封装可以通过类将数据以及操作数据的方法进行有机结合通过访问权限来隐藏对象内部实现细节控制哪些方法可以在类外部直接被使用。 再例如我们使用C实现栈与C语言实现栈进行对比 C语言实现栈 #includestdio.h ... typedef int DataType; typedef struct Stack {DataType* a;int capacity;int Top; }Stack; void StackInit(Stack* ps){assert(ps);...; } void StackPush(Stack* ps, DataType data){assert(ps);...; } void StackPop(Stack* ps){assert(ps);...; }........ int main() {Stack s1;StackInit(s);StackPush(s, 3);StackDestroy(s);return 0; }C实现栈 #includeiostream using namespeace std; ... typedef int DataType; class Stack { public:void Init(Stack* ps) {assert(ps);...;}void Push(Stack* ps, DataType data) {assert(ps);...;}void Pop(Stack* ps) {assert(ps);...;}........ private:DataType* a;int capacity;int Top; };int main() {Stack s1;Stack.Init(s);Stack.Push(s, 3);Stack.Destroy(s);return 0; }对比就会发现C语言可以随便访问数据结构本身容易造成安全问题而C只允许使用成员函数来访问数据结构本身避免了这样的安全性问题而且使用起来更加简单方便。 C把栈中用到的所有函数和变量放在一起对外封装成一个类这也是封装的一种体现。 四、类的实例化 1、类的实例化概念 我们在类中定义的变量其实是变量声明与函数声明类似在定义类时操作系统并不会给我们开辟空间只有我们用类去定义对象时操作系统才会给我们开辟空间用类类型创建对象的过程我们称为类的实例化。 我们可以将类比作建筑图纸别墅就是建筑图纸的实例化那么对象就是类的实例化。 class test {int a;//变量的声明int b;//变量的声明 }; int main() {test t1;//用test类实例化了一个t1的对象return 0; } 2、类对象的大小的计算 一个类可以实例化出多个对象实例化出的对象 占用实际的内存空间存储成员变量那么我们如何计算类的大小呢 废话少说这里我们C类的大小继承了C语言结构体大小的计算也是按照结构体内存对齐规则 【结构体内存对齐规则】 第一个成员在与结构体偏移量为0的地址处。其他成员变量要对齐到某个数字对齐数的整数倍的地址处。 注意对齐数 编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的对齐数为8结构体总大小为最大对齐数所有变量类型最大者与默认对齐参数取最小的整数倍。如果嵌套了结构体的情况嵌套的结构体对齐到自己的最大对齐数的整数倍处结构体的整体大小就是所有最大对齐数含嵌套结构体的对齐数的整数倍。 请你计算一下32位平台下Date类的大小 class Date { public:void print(){cout_year/_month/_day/endl;} private:int _year;int _month;int _day; };正确答案是12三个变量的对齐数都是4类的最大对齐数为4从前到后中间没有多余空间依次排列故为12。 你可能会说为什么不是16呢函数print用一个函数指针存储起来而且32位平台下一个函数指针刚好占用4个字节。能想出这个问题说明你对函数指针学习的很好但是呢我首先明确告诉你在C的类中类的大小只计算成员变量不计算成员函数再其次我们来讨论为什么C的类中不计算成员函数的大小 我们看下面一段代码我们调用的两个函数Init()是不是同一个函数呢 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;Date d2;d1.Init(2023, 2, 9);d2.Init(2023, 2, 10);return 0; }答案是是的我们调用的是同一个函数如果我们把成员函数也算进类的大小中那么我们每次创建每个对象时都要为函数指针分配空间当我们创建许多对象时它们调用函数时都用同一个地址都要去调用同一个函数但是呢每个对象要有一个指针存储去存放相应函数地址这就造成了一个函数的地址被许多个指针存储内存空间造成了很大的浪费。 于是我C就把成员函数全部放进一个叫公共区域这个公共区域叫中叫做代码段那个对象调用函数就去代码段中找相应的函数。 扩展知识可以忽略 C/C程序内存分配的几个区域 栈区stack在执行函数时函数内局部变量的存储单元都可以在栈上创建函数执行结 束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中效率很高但是 分配的内存容量有限。 栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返 回地址等。堆区heap一般由程序员分配释放 若程序员不释放程序结束时可能由OS回收 。分 配方式类似于链表。数据段静态区static存放全局变量、静态数据。程序结束后由系统释放。代码段存放函数体类成员函数和全局函数的二进制代码。 有了上面的知识后我们再计算两个类的大小 // 类中仅有成员函数 class A2 { public:void f2(){} }; // 类中什么都没有---空类 class A3 { };你可能认为它们是0但是那也太奇怪了吧定义一个对象但是对象不占用内存 其实这种类中仅有成员函数或类中什么都没有的空类都是比较特殊的编译器给了这种类一个字节来唯一标识这个类的对象。 五、this指针 this是C 63个关键字中的一个。 对于它的理解我们先看一段代码 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语言实现这段代码的同样功能在我们调用Init()与 Print() 函数时会采用传指针的方式这个指针就可以帮我们区分不同的对象。 typedef struct Date {int _year; // 年int _month; // 月int _day; // 日 }Date; void Init(Data*pd,int year, int month, int day) {pd-_year year;pd-_month month;pd-_day day; } void Print(Data*pd) {cout pd- _year - pd-_month - pd-_day endl; } int main() {Date d1, d2;Init(d1,2022, 1, 11);Init(d2,2022, 1, 12);Print(d1);Print(d2);return 0; } 与C语言不同的是C中通过引入this指针解决该问题即C编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数让该指针指向当前对象(函数运行时调用该函数的对象)在函数体中所有“成员变量”的操作都是通过该指针去访问。只不过所有的操作对用户是透明的即用户不需要来传递编译器自动完成。 上面的标准回答翻译成大白话就是C的实现原理与C语言一样对象d1调用函数的话this指针就存储d1的地址,在传递参数时只不过我们不用自己传递指针了是由编译器自动帮我们传递了指针。 C实现的真实方式 class Date { public:void Init(Date*this,int year, int month, int day)//此处只是为了演示Date*this不用我们手动传递//编译器会自动传递我们手动传递会报错{this-_year year;//此处的this-可以省略this-_month month;//此处的this-可以省略this-_day day;//此处的this-可以省略}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; }this指针的特性 this指针的类型类型* const即成员函数中不能给this指针赋值。只能在“成员函数”的内部使用this指针本质上是“成员函数”的形参当对象调用成员函数时将对象地址作为实参传递给this形参所以对象中不存储this指针。this指针是“成员函数”第一个隐含的指针形参一般存在与栈中因为它的本质是函数形参VS通过ecx寄存器存储。
http://www.hkea.cn/news/14539370/

相关文章:

  • 手机网站底部广告代码免费咨询律师电话
  • 360免费建站视频wordpress_主题教程
  • 汽车装饰网站模板网站未被百度中收录的原因
  • 网站建设多少钱兴田德润放心深圳自适应网站
  • 宁波营销型网站建设首选广州宝安建网站
  • 国家建设部网站倪虹小程序代理商在哪儿
  • 上海高端网站建设服务公学校做网站的软件
  • 做网站要租服务器全球速卖通的特点
  • 深圳市建设工程造价管理站微信开放平台是干什么的
  • 河南县wap网站建设公司品牌网络推广方式
  • 5网站建站做盗版电影网站吗
  • 美食网站源代码郑州集团网站建设哪家好
  • 网站推广实施计划wordpress学习教程
  • 江苏网站建设费用他达拉非说明书
  • 小学生家长网站建设需求wordpress实例网址
  • 设计素材网站新媒体营销策略
  • 网站经常做封面的那些番号建网站定制
  • 网站后台上传图片显示运行错误为什么沈阳制作网站企业
  • 安徽省美好乡村建设网站电商网站设计模板
  • 可以做软件的网站有哪些ui界面图标
  • 网站开发语言排行中国商标买卖网站
  • 大连网站快速排名龙南黄页全部电话
  • 天津网站建设noakj乐清网络科技有限公司
  • 郑州 网站建设 东区wordpress主题vieu
  • 如何提高网站点击率怎么做网站前台如何刷新
  • 网站开发建设流程南昌模板建站代理
  • 网站建设的岗位要求深圳网站免费制作
  • 南昌商城网站建设公司广告设计公司实习周记
  • 网站建设设计报告青岛微网站制作
  • wordpress主题详情更改版权如何做360网站优化