在浏览器播放视频,成都seo整站,平台型网站建设,网站关键词被改前言
上一期我们介绍了一些C入门的基础知识#xff0c;本期我们来介绍面向对象。初步认识一下面向对象和面向过程、类、以及封装#xff01;
本期内容介绍 面向过程和面向对象 类的引入 类的定义 类的访问限定符和封装 类的作用域 类的实例化 类对象模型 this指针 一、面向…前言
上一期我们介绍了一些C入门的基础知识本期我们来介绍面向对象。初步认识一下面向对象和面向过程、类、以及封装
本期内容介绍 面向过程和面向对象 类的引入 类的定义 类的访问限定符和封装 类的作用域 类的实例化 类对象模型 this指针 一、面向过程和面向对象 面向过程C语言关注的是过程即分析出求解问题的步骤通过函数调用逐步解决问题。而面向对象C关注的是对象即解决的事情被分成不同的对象各个对象配合完成。 以前我也不怎么理解面向对象和面向过程后来看到了很多例子后逐渐有了理解我来举一个我以前理解最好的例子 --- 洗衣服。 面向过程用面向过程来洗衣服的步骤找盆 --- 接水 --- 放洗衣液 --- 放衣服 --- 手搓 --- 换水 --- 再洗 --- 换水 --- 拧干 --- 晾晒。你得关注每一步的过程 面想对象用面向对象来洗衣服的步骤人、衣服、洗衣机、洗衣液。整个过程就是人将衣服洗衣液放到洗衣机中启动洗衣机洗衣机洗好了会烘干具体的洗衣服和烘干过程你根本不用关心这是洗衣机的事情 当然还有其他同类的例子例如把大象装到冰箱里面
二、类的引入 C语言的struct只能定义变量在C中不仅可以定义变量而且可以定义函数。例如我们以前C语言中玩的栈就是只能在结构中定义变量而C中可以定义函数 C语言版本
typedef int STDataType;
struct Stack
{STDataType* a;int top;int capacity;
};
他的方法只能在外面而C就可以在里面
C版本
#include iostreamtypedef int STDataType;
struct Stack
{STDataType* _a;int _top;int _capacity;void Init(int capacity 4){_a (STDataType*)malloc(sizeof(STDataType) * capacity);if (_a nullptr){perror(malloc failed);exit(-1);}_capacity capacity;_top 0;}//...
};
上述操作可以但C中更喜欢用class来替代struct
三、类的定义
class ClassName
{//成员变量和成员方法函数
};//注意封号 class是C中定义类的关键字ClassName 是类的名字 {}中为是类的主体。和struct一样结束的 ; 不能省略 类体中(即{}中)的内容被称为类的成员成员被分为变量和函数。成员变量又被称为成员的属性用来描述该对象的特征成员函数又被成为成员方法是描述类的行为的 类的两种定义方式 1、声明和定义全部放在类体中需要注意的是成员函数在类体中默认是内联的 class Student
{
public://成员方法void sleep(){cout _name 正在sleep()... endl;}private://成员属性char* _name;char* _sex;int _age;
};
当然这里用struct也可以定义类 2、声明和定义分开即声明放在.h定义在.cpp中时在定义的成员函数名前需要加类名和作用域限定符::来指定是哪个域的 小tips: 我们一般建议使用第二种 成员变量的命名规则 我一般习惯时在成员属性的成员的前面加一个下划线这个的作用主要是区分形参和成员属性的。具体怎么加看你的想法以及需求只要能分开都可以但也要符合我们以前C语言介绍过的标识符命名规则如下就是C语言的表示符命名规则 标识符只能由字母、数字和下划线组成。标识符必须以字母或下划线开头不能以数字开头。标识符区分大小写。标识符的长度没有限制但只有前31个字符有效。C语言的关键字如if、for、while等不能用作标识符。标识符不能包含空格或其他特殊字符如、#、$等。一般情况下标识符应具有描述性和易于理解的名称。 四、类的访问限定符和封装
访问限定符 C中访问限定符有三个分别是public(公有的)protected(被保护的)private(私有的) 访问限定符的说明 public修饰的成员在类外可以直接访问 protec和private修饰的成员再类外面不能直接访问(目前认为他两一样到后面介绍了继承、多态再解释他两的区别) 访问权限的作用域从该访问限定符开始到下一个访问限定符结束 如果没有出现下一个访问限定符则到}终止 class的默认访问权限是private的struct为public的(因为struct要兼容C语言) 注意访问限定符只要编译时有效当数据映射到内存后没有任何访问限定符上的区别 OK 举个栗子看看
public在类外可以访问以属性举例方法同理
class Stack
{
public:void Init(int capacity 3){_a (int*)malloc(sizeof(int) * capacity);if (_a nullptr){perror(malloc failed);exit(-1);}_size 0;_capacity capacity;}void Push(int x){//...}int* _a;int _size;int _capacity;
};int main()
{Stack s;s.Init();cout s._size endl;return 0;
} 这里把class直接换成struct也可以
private/protectedd当前认为是一样的在类外不可访问 C中struct和class的区别是什么 C需要兼容C语言所以C中的struct可以当成结构体使用。另外C中的struct还可以和class一样用来定义类。区别是struct定义类的访问权限是publicclass定义的类的访问权限是private。另外在继承和模板参数列表位置也是与区别的后期介绍了会在拿出来介绍的 注意在C中如果用struct定义结构体的话在结构体类在申明结构体变量时不用在struct了
struct SLNode
{int* data;SLNode* next;
}; 原因是C对struct进行了升级变成了类用它定义的就是一个类型所以就可以直接用C语言是struct _name{}才是一个类型 封装 理论层面C实现封装的方式用类将对象的属性和方法结合到一块让对象更加完善通过访问权限来隐藏内部具体的实现细节选择性的把其部分接口提供给外部调用者用户。 代码层面在C类的内部把不想让类外部直接访问的成员用private修饰外部要访问只能使用提供公开的接口 封装的本质是一种管理为了让用户使用起来方便 OK来举一个栗子。你现在看这篇博客的手机或电脑它的组成较为复杂他只给用户提供开机键输入输出设备即键盘显示器等让用户和计算机能进行交互的接口但他真正工作的是CPU显卡等硬件但你用关心这些吗是不是不用啊你只需要在人家给你的提供的接口上操作即可管他的谁工作、如何工作。只要能完成你的操作即可~ 五、类的作用域 类定义了一个新的作用域类的所有成员都在类的作用域中。在类外面定义时需要使用::作用域限定符来指定成员属于哪个类 class Date
{
public:void Init(int year 1, int month 1, int day 1){_year year;_month month;_day day;}void Print();private:int _year;int _month;int _day;
};//这里注意要指定Print属于Date这个类
void Date::Print()
{cout 999 endl;
}
六、类的实例化 用类类型创建对象的过程称为类的实例化。 //类
class Date
{
public:void Init(int year 1, int month 1, int day 1){_year year;_month month;_day day;}void Print(){cout _year - _month - _day endl;}private:int _year;int _month;int _day;
};int main()
{Date d;//实例化一个对象d.Init(2023, 11, 25);d.Print();return 0;
}
1、类是描述对象的是一个模型模板它限制了类有哪些成员定义出一个类并没有分配实际的内存空间来存储他。例如开学时填写的学生信息表这个表可以看成一个学生类他来描述具体的学生对象
2、一个类可以实例化多个对象实例化出来的对象占用实际的物理空间存储类成员变量 例如刚刚上面说的把学生开学的信息表看做一个学生类的话每登记一个学生就实例化了一个对象而这个表可以被很多学生填写实例化多个对象每个实例化出来的学生对象才有自己的实际空间例如宿舍这些学生有属于自己的年龄、姓名、性别等成员属性 或者你可以把盖楼房的图纸理解成一个类按照这个图纸可以修很多的房子(实例化多个对象)图纸本身不占实际的空间真正占空间的是按照图纸盖的房子这些实例化的房子有客厅、卧室等属性 七、类对象模型
上面我们已经清楚了类的定义以及其实例化对象。一个对象有成员属性也有成员的方法而我们想知道的是一个对象包含了什么
OK关于这个问题我就直接先说结论再解释了 一个对象包含了成员属性和成员方法。成员属性是对象自身的属性(成员变量),也就是说成员属性属于对象。而成员方法是这个类都有的行为是属于类所有类的对象都有成员。 我用一个我家鸽鸽的例子来说明我家鸽鸽属于人这个类他的名字和性别等是他个人独属于的他的成员方法行为有唱、条、rap、打篮球。但只有我家鸽鸽会唱、条、rap、打篮球吗你是不是也可以啊所以类的成员方法属于类
class People
{
public://方法属于整个类void Sing(){cout 鸡你太美~... endl;}private://属性属于对象本身char _name[20];char _sex[5];int age;
};
如何计算一个类的大小 可以用sizeof这个操作符来计算类的大小一个类的大小是该类中的成员变量之和不包含静态成员变量虽然静态成员变量属于类但对类的大小无影响当然要注意内存对齐如果是没有成员变量的类编译器会给一个字节来唯一标识这个类 //既有成员变量又有成员方法的类
class A
{
public:void Print(){//...}private:int a;
};//只有成员方法没有成员变量的类
class B
{
public:void Print(){//...}
};//既没有成员变量有没有成员方法的类空类
class C
{};int main()
{cout sizeof(A) endl;cout sizeof(B) endl;cout sizeof(C) endl;return 0;
} 目前我们可以认为类的大小和对象的大小是一样的一个是在图纸上算空间一个是实地测量 结构体内存对齐规则和C语言的一样 1.结构的第一个成员变量永远放在相较于结构体起始位置偏移量为0处 2.从第二个开始后面的每个元素都要对齐到某个对齐数的整数倍处对齐数结构体成员自身大小和默认对齐数的较小值 在VS上默认对齐数是8而在gcc是没有默认对齐数的对齐数就是成员的自身大小 3.结构体的总大小必须是最大对齐数的整数倍。最大对齐数所有成员的对齐数中的最大值 4.如果嵌套了结构体的情况嵌套的结构体对齐到自己的最大对齐数的整数倍处结构体的整体大小就是所有最大对齐数的整数倍包含嵌套结构体的对齐数 如果这块还有问题请点击后面的链接这篇博文中我详细介绍过它的计算和栗子
内存对齐
八、this指针
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;d1.Init(2023, 11, 25);d1.Print();Date d2;d2.Init(2023, 11, 26);d2.Print();return 0;
} Init和Print是类的成员方法我们并没有指定是哪个对象的为什么我们在调d1.Init的时候就是给d1对象赋值而不是给d2初始化呢我们在d2.Print的时候是打印d2的属性的信息为什么不打印d1会随机值呢他到底是如何区别的呢 C为了解决上述的问题引入了this指针来解决C编译器给每一个非静态的成员函数都增加了一个隐藏的指针参数让这个指针指向当前对象函数运行时调用该函数的对象在函数体中所有的成员变量的操作都是通过该指针去访问的。只不过所有的操作对用户是不可见的也不需要用户手动传编译器会自动完成 this指针的特性 1、this指针的类型类类型* const 即此时的const修饰this只能在形参接受被实参拷贝的时候赋值一次在成员函数中不能给this赋值 2、this只能在成员函数非静态成员函数静态的成员函数没有this后面会再解释内部使用可以显示的写 3、this指针本质上是成员函数的形参非静态成员函数当对象调用成员函数将对象的地址会传给this所以对象不存储this指针 4、this指针是成员函数非静态成员函数第一个隐含的指针参数形参一般情况由寄存器ecx自动传递调用者不需要手动传递 this指针存在哪里this指针可以为空吗 这应该是这里很坑的两个问题了对基础考察很细OK我还是先说结论再用栗子来解释 this指针是形参存储在函数栈帧上this可以为空但为空时不能去访问成员属性否则就是则空指针异常操作了 OK两个栗子分别解释一下
栗子1下列程序的编译运行的结果是A、编译报错 B、运行奔溃 C、正常运行
class A
{
public:void Print(){cout Print() endl;}
private:int _a;
};int main()
{A* p nullptr;p-Print();return 0;
}
OK他是C、正常运行我们来看一下 原因是这里虽然p是nullptr但他是个对象指针他-Print是调用类的方法当然没有问题他调用Print传参的时候的确是nullpttrthis指针接收的是nullptr但他没有访问成员属性啊所以不会报错正常运行 这里可能有点绕我来举个栗子这里的p假设是一个叫张三驴的学霸它的分数是700他可不可以报清华当然可以。人家之人你的分数不管你的人。这里也是一样人家直看你是不是类的对象不管你是不是nullptr 。咱们的张三驴同学虽然收到了很多学校的抢人电话并提前发了录取通知书但他不去上是不是就和他没有关系了。这里也是一样我this的确是nullptr但我没用它访问成员变量呀 栗子2下列程序的编译运行的结果是A、编译报错 B、运行奔溃 C、正常运行 class A
{
public:void PrintA(){cout _a endl;}
private:int _a;
};int main()
{A* p nullptr;p-PrintA();return 0;
}
OK这里是B、运行崩溃 原因是对空指针进行了操作和上面的不一样的是下面的Print访问了成员员变量_a这就出问题了this是空指向一块不存在的内存你咋访问就出问题了还是上面的例子我们的张三驴同学不小心收到了清京大学一激动以为是那两所顶尖高校合作的一个学校。可高兴了结果把学费一交都查不到学校地址~..... C语言和C实现栈的对比
C语言
#include assert.h
typedef int DataType;
typedef struct Stack
{DataType* array;int capacity;int size;
}Stack;void StackInit(Stack* ps)
{assert(ps);ps-array (DataType*)malloc(sizeof(DataType) * 3);if (NULL ps-array){assert(0);return;}ps-capacity 3;ps-size 0;
}void StackDestroy(Stack* ps)
{assert(ps);if (ps-array){free(ps-array);ps-array NULL;ps-capacity 0;ps-size 0;}
}void CheckCapacity(Stack* ps)
{if (ps-size ps-capacity){int newcapacity ps-capacity * 2;DataType* temp (DataType*)realloc(ps-array,newcapacity * sizeof(DataType));if (temp NULL){perror(realloc申请空间失败!!!);return;}ps-array temp;ps-capacity newcapacity;}
}void StackPush(Stack* ps, DataType data)
{assert(ps);CheckCapacity(ps);ps-array[ps-size] data;ps-size;
}int StackEmpty(Stack* ps)
{assert(ps);return 0 ps-size;
}void StackPop(Stack* ps)
{if (StackEmpty(ps))return;ps-size--;
}DataType StackTop(Stack* ps)
{assert(!StackEmpty(ps));return ps-array[ps-size - 1];}int StackSize(Stack* ps)
{assert(ps);return ps-size;
}int main()
{Stack s;StackInit(s);StackPush(s, 1);StackPush(s, 2);StackPush(s, 3);StackPush(s, 4);printf(%d\n, StackTop(s));printf(%d\n, StackSize(s));StackPop(s);StackPop(s);printf(%d\n, StackTop(s));printf(%d\n, StackSize(s));StackDestroy(s);return 0;
} 可以看到在用 C 语言实现时 Stack 相关操作函数有以下共性 每个函数的第一个参数都是 Stack* 函数中必须要对第一个参数检测因为该参数可能会为 NULL 函数中都是通过 Stack* 参数操作栈的 调用时必须传递 Stack 结构体变量的地址 结构体中只能定义存放数据的结构操作数据的方法不能放在结构体中即 数据和操作数据 的方式是分离开的 而且实现上相当复杂一点涉及到大量指针操作稍不注意可能就会出 错。 C:
typedef int DataType;
class Stack
{
public:void Init(){_array (DataType*)malloc(sizeof(DataType) * 3);if (NULL _array){perror(malloc申请空间失败!!!);return;}_capacity 3;_size 0;}void Push(DataType data){CheckCapacity();_array[_size] data;_size;}void Pop(){if (Empty())return;_size--;}DataType Top() { return _array[_size - 1]; }int Empty() { return 0 _size; }int Size() { return _size; }void Destroy(){if (_array){free(_array);_array NULL;_capacity 0;_size 0;}}private:void CheckCapacity(){if (_size _capacity){int newcapacity _capacity * 2;DataType* temp (DataType*)realloc(_array, newcapacity *sizeof(DataType));if (temp NULL){perror(realloc申请空间失败!!!);return;}_array temp;_capacity newcapacity;}}private:DataType* _array;int _capacity;int _size;
};int main()
{Stack s;s.Init();s.Push(1);s.Push(2);s.Push(3);s.Push(4);printf(%d\n, s.Top());printf(%d\n, s.Size());s.Pop();s.Pop();printf(%d\n, s.Top());printf(%d\n, s.Size());s.Destroy();return 0;
} C 中通过类可以将数据 以及 操作数据的方法进行完美结合通过访问权限可以控制那些方法在 类外可以被调用即封装 在使用时就像使用自己的成员一样更符合人类对一件事物的认知。 而且每个方法不需要传递 Stack* 的参数了编译器编译之后该参数会自动还原即 C 中 Stack * 参数是编译器维护的 C 语言中需用用户自己维护 。 文章转载自: http://www.morning.tfkqc.cn.gov.cn.tfkqc.cn http://www.morning.jjhrj.cn.gov.cn.jjhrj.cn http://www.morning.nlywq.cn.gov.cn.nlywq.cn http://www.morning.qpnb.cn.gov.cn.qpnb.cn http://www.morning.ynstj.cn.gov.cn.ynstj.cn http://www.morning.qdlnw.cn.gov.cn.qdlnw.cn http://www.morning.gwdkg.cn.gov.cn.gwdkg.cn http://www.morning.ykmtz.cn.gov.cn.ykmtz.cn http://www.morning.cpzkq.cn.gov.cn.cpzkq.cn http://www.morning.vibwp.cn.gov.cn.vibwp.cn http://www.morning.rcmcw.cn.gov.cn.rcmcw.cn http://www.morning.lxqyf.cn.gov.cn.lxqyf.cn http://www.morning.hffpy.cn.gov.cn.hffpy.cn http://www.morning.mmxt.cn.gov.cn.mmxt.cn http://www.morning.nrlsg.cn.gov.cn.nrlsg.cn http://www.morning.xjmyq.com.gov.cn.xjmyq.com http://www.morning.rtkgc.cn.gov.cn.rtkgc.cn http://www.morning.tnrdz.cn.gov.cn.tnrdz.cn http://www.morning.bmjfp.cn.gov.cn.bmjfp.cn http://www.morning.rpfpx.cn.gov.cn.rpfpx.cn http://www.morning.hgsmz.cn.gov.cn.hgsmz.cn http://www.morning.fgkrh.cn.gov.cn.fgkrh.cn http://www.morning.zttjs.cn.gov.cn.zttjs.cn http://www.morning.ytbr.cn.gov.cn.ytbr.cn http://www.morning.qnywy.cn.gov.cn.qnywy.cn http://www.morning.ndmh.cn.gov.cn.ndmh.cn http://www.morning.kdjtt.cn.gov.cn.kdjtt.cn http://www.morning.xbxks.cn.gov.cn.xbxks.cn http://www.morning.hrydl.cn.gov.cn.hrydl.cn http://www.morning.mlnzx.cn.gov.cn.mlnzx.cn http://www.morning.xzrbd.cn.gov.cn.xzrbd.cn http://www.morning.fkgcd.cn.gov.cn.fkgcd.cn http://www.morning.wtsr.cn.gov.cn.wtsr.cn http://www.morning.reababy.com.gov.cn.reababy.com http://www.morning.jcxqc.cn.gov.cn.jcxqc.cn http://www.morning.mgbsp.cn.gov.cn.mgbsp.cn http://www.morning.hyryq.cn.gov.cn.hyryq.cn http://www.morning.ryxdf.cn.gov.cn.ryxdf.cn http://www.morning.ns3nt8.cn.gov.cn.ns3nt8.cn http://www.morning.rwbx.cn.gov.cn.rwbx.cn http://www.morning.pqnkg.cn.gov.cn.pqnkg.cn http://www.morning.lhrxq.cn.gov.cn.lhrxq.cn http://www.morning.lfjmp.cn.gov.cn.lfjmp.cn http://www.morning.zbkwj.cn.gov.cn.zbkwj.cn http://www.morning.fjlsfs.com.gov.cn.fjlsfs.com http://www.morning.swdnr.cn.gov.cn.swdnr.cn http://www.morning.cwwbm.cn.gov.cn.cwwbm.cn http://www.morning.fwqgy.cn.gov.cn.fwqgy.cn http://www.morning.nzsx.cn.gov.cn.nzsx.cn http://www.morning.dmsxd.cn.gov.cn.dmsxd.cn http://www.morning.gqfbl.cn.gov.cn.gqfbl.cn http://www.morning.hblkq.cn.gov.cn.hblkq.cn http://www.morning.hcsnk.cn.gov.cn.hcsnk.cn http://www.morning.nldsd.cn.gov.cn.nldsd.cn http://www.morning.mrfnj.cn.gov.cn.mrfnj.cn http://www.morning.lfgql.cn.gov.cn.lfgql.cn http://www.morning.lltdf.cn.gov.cn.lltdf.cn http://www.morning.xnnxp.cn.gov.cn.xnnxp.cn http://www.morning.mwzt.cn.gov.cn.mwzt.cn http://www.morning.cqyhdy.cn.gov.cn.cqyhdy.cn http://www.morning.xrtsx.cn.gov.cn.xrtsx.cn http://www.morning.piekr.com.gov.cn.piekr.com http://www.morning.frpm.cn.gov.cn.frpm.cn http://www.morning.ktmnq.cn.gov.cn.ktmnq.cn http://www.morning.sypby.cn.gov.cn.sypby.cn http://www.morning.ktlxk.cn.gov.cn.ktlxk.cn http://www.morning.hqzmz.cn.gov.cn.hqzmz.cn http://www.morning.tstwx.cn.gov.cn.tstwx.cn http://www.morning.pbxkk.cn.gov.cn.pbxkk.cn http://www.morning.pcgjj.cn.gov.cn.pcgjj.cn http://www.morning.wzknt.cn.gov.cn.wzknt.cn http://www.morning.drhnj.cn.gov.cn.drhnj.cn http://www.morning.dhdzz.cn.gov.cn.dhdzz.cn http://www.morning.rbhqz.cn.gov.cn.rbhqz.cn http://www.morning.dfkby.cn.gov.cn.dfkby.cn http://www.morning.qsmdd.cn.gov.cn.qsmdd.cn http://www.morning.dnbhd.cn.gov.cn.dnbhd.cn http://www.morning.kwwkm.cn.gov.cn.kwwkm.cn http://www.morning.mzskr.cn.gov.cn.mzskr.cn http://www.morning.bxgpy.cn.gov.cn.bxgpy.cn