行业资讯
【C++初阶】类和对象(一):面向对象基础核心详解
1. 类的定义1.1类定义格式class 类名{};class是定义类的关键字{}中的为类的主体类定义结束时最后的分号不能省略。类体中的内容称为类的成员类中的变量称为类的属性或成员变量类中的函数称为类的类的方法或成员函数。为了区分成员变量一般习惯上成员变量会加一个特殊标识如成员变量前面或后面加_或者m开头不是强制的只是惯例。C中struct也可以定义类C兼容C中struct的用法同时struct升级成了类明显的变化是struct中可以定义函数一般情况下推荐使用class定义类。class 和struct定义类的区别是class默认访问限定符是私有struct默认访问限定符是公有。定义在类里的函数默认是inline。声明和定义分离不是inline。#includeassert.h#includeiostreamusingnamespacestd;classStack{public:// 成员函数voidInit(intn4){array(int*)malloc(sizeof(int)*n);if(arraynullptr){perror(malloc申请空间失败);return;}capacityn;top0;}voidPush(intx){// ...扩容array[top]x;}intTop(){assert(top0);returnarray[top-1];}voidDestroy(){free(array);arraynullptr;topcapacity0;}private:// 成员变量int*array;size_t capacity;size_t top;};// 分号不能省略intmain(){Stack st;st.Init();st.Push(1);st.Push(2);coutst.Top()endl;st.Destroy();return0;}classDate{public:voidInit(intyear,intmonth,intday){_yearyear;_monthmonth;_dayday;}private:// 为了区分成员变量一般习惯上成员变量会加一个特殊标识如_或m开头int_year;// year_ 或 m_yearint_month;int_day;};#includeiostreamusingnamespacestd;// C将struct升级成了类// 1.类里可以定义函数// 2.struct名称可以代表类型// C中兼容C中struct的用法typedefstructListNodeC{structListNodeC*next;intval;}LTNode;// 不再需要typedefListNodeCPP也可以代表类型structListNodeCPP{voidInit(intx){nextnullptr;valx;}ListNodeCPP*next;intval;};intmain(){return0;}1.2访问限定符访问限定符有三个public、private、protectedC一种实现封装的方式用类将对象的属性与方法结合在一块让对象更加完善通过访问权限选择性的将接口提供给外部的用户使用public修饰的成员在类外可以直接被访问protected和private修饰的成员在类外不能直接被访问。访问限定符的作用域从该访问限定符出现的位置开始直到下一个访问限定符出现为止如果后面没有访问限定符作用域就到}即类结束。class定义成员没有被访问限定符修饰时默认为privatestruct默认为public。一般成员变量都会被限制为private/protected需要给别人使用的成员函数会放为public。1.3类域类定义了一个新的作用域类的所有成员都在类的作用域中在类体外定义成员声明和定义分离时需要使用::作用域操作符指明成员属于哪个类域。类域影响的是编译时的查找规则下面程序中Init如果不指定类域Stack那么编译器就会把Init当成全局函数那么编译时找不到array等成员的声明/定义就会报错。指定类域Stack就是知道Init是成员函数当前域找不到array等成员就会到类域中查找。#includeiostreamusingnamespacestd;classStack{public:// 成员函数voidInit(intn4);private:// 成员变量int*array;size_t capacity;size_t top;};// 声明和定义分离需要指定类域voidStack::Init(intn){array(int*)malloc(sizeof(int)*n);if(nullptrarray){perror(malloc申请空间失败);return;}capacityn;top0;}intmain(){Stack st;st.Init();return0;}2.实例化2.1实例化概念用类类型在物理内存中创建对象的过程称为类实例化出对象。类是对象进行一种抽象化描述是一个模型一样的东西限定了类有哪些成员变量这些成员变量只是声明没有分配空间用类实例化出对象时才会分配空间。一个类可以实例化出多个对象实例化出的对象占用实际的物理空间存储类成员变量。#includeiostreamusingnamespacestd;classDate{public:voidInit(intyear,intmonth,intday){_yearyear;_monthmonth;_dayday;}voidPrint(){cout_year/_month/_dayendl;}private:// 这里只是声明没有开空间int_year;int_month;int_day;};intmain(){// Date实例化出对象d1和d2Date d1;Date d2;d1.Init(2026,1,13);d1.Print();d2.Init(2026,1,1);d2.Print();return0;}2.2对象大小对象中只存储成员变量C规定类实例化的对象也要符合内存对齐的规则内存对齐规则第一个成员在与结构体偏移量为0的地址处其他成员变量要对齐到某个数字对齐数的整数倍的地址处对齐数 编译器默认的对齐数与该成员大小的较小值VS中的默认对齐是8结构体总大小为最大对齐数所有变量类型最大者与默认对齐参数取最小的整数倍如果嵌套了结构体的情况嵌套的结构体对齐到自己的最大最大对齐数的整数倍处结构体的整体大小就是所有最大对齐数含嵌套结构体的对齐数的整数倍#includeiostreamusingnamespacestd;classA{public:voidPrint(){cout_chendl;}private:char_ch;int_i;};classB{public:voidPrint(){// ...}};classC{};intmain(){A a;B b;C c;coutsizeof(a)endl;coutsizeof(b)endl;coutsizeof(c)endl;return0;}这个程序中B和C中没有成员变量但大小是1是为了占位标识对象存在。3.this指针编译器编译后类的成员函数默认都会在形参的第一个位置增加一个当前类类型的指针叫做this指针。比如Date类真实原型为void Init(Dateconst this, int year, int month, int day);*类的成员函数中访问成员变量本质都是通过this指针访问的如Init函数中给_year赋值this-_year year;C规定不能在实参和形参的位置显式的写this指针编译时编译器会处理但是可以在函数体内显式的使用this指针。this指针存在内存的栈区#includeiostreamusingnamespacestd;classDate{public:// void Init(Date* const this, int year, int month, int day)voidInit(intyear,intmonth,intday){// this-_year year;_yearyear;this-_monthmonth;this-_dayday;}voidPrint(){cout_year/_month/_dayendl;}private:// 这里只是声明没有开空间int_year;int_month;int_day;};intmain(){// Date实例化出对象d1和d2Date d1;Date d2;//d1.Init(d1, 2026, 1, 13);d1.Init(2026,1,13);d1.Print();d2.Init(2026,1,1);d2.Print();return0;}4.C语言和C实现stack对比C语言#includestdio.h#includestdlib.h#includestdbool.h#includeassert.htypedefintSTDataType;typedefstructStack{STDataType*a;inttop;// 栈顶intcapacity;// 容量}ST;// 初始化voidSTInit(ST*pst){assert(pst);pst-aNULL;// top指向栈顶元素的下一个位置pst-top0;pst-capacity0;}// 销毁voidSTDestroy(ST*pst){free(pst-a);pst-aNULL;pst-capacity0;}// 入栈voidSTPush(ST*pst,STDataType data){assert(pst);if(pst-toppst-capacity){intnewCapacitypst-capacity0?4:pst-capacity*2;STDataType*tmp(STDataType*)realloc(pst-a,2*newCapacity*sizeof(STDataType));if(tmpNULL){perror(realloc fail);return;}pst-atmp;pst-capacitynewCapacity;}pst-a[pst-top]data;pst-top;}// 出栈voidSTPop(ST*pst){assert(pst);assert(pst-top0);pst-top--;}// 获取栈顶元素STDataTypeSTTop(ST*pst){assert(pst);assert(pst-top0);returnpst-a[pst-top-1];}// 判空boolSTEmpty(ST*pst){assert(pst);returnpst-top0;}// 获取元素个数intSTSize(ST*pst){assert(pst);returnpst-top;}intmain(){ST s;STInit(s);STPush(s,1);STPush(s,2);STPush(s,3);STPush(s,4);printf(%d\n,STTop(s));printf(%d\n,STSize(s));while(!STEmpty(s)){printf(%d ,STTop(s));STPop(s);}STDestroy(s);return0;}C#includeassert.h#includeiostreamusingnamespacestd;typedefintSTDataType;classStack{public://成员函数voidInit(intn4){_a(STDataType*)malloc(sizeof(STDataType)*n);if(nullptr_a){perror(malloc fail);return;}_capacityn;_top0;}voidPush(STDataType x){if(_top_capacity){intnewCapacity_capacity*2;STDataType*tmp(STDataType*)realloc(_a,newCapacity*sizeof(STDataType));if(tmpNULL){perror(realloc fail);return;}_atmp;_capacitynewCapacity;}_a[_top]x;}voidPop(){assert(_top0);--_top;}boolEmpty(){return_top0;}intTop(){assert(_top0);return_a[_top-1];}voidDestroy(){free(_a);_anullptr;_top_capacity0;}private://成员变量STDataType*_a;size_t _capacity;size_t _top;};intmain(){Stack s;s.Init();s.Push(1);s.Push(2);s.Push(3);s.Push(4);while(!s.Empty()){printf(%d\n,s.Top());s.Pop();}s.Destroy();return0;}
郑州网站建设
网页设计
企业官网