阿里巴巴国际站下载电脑版,企业标准信息公共服务平台官网,搜索引擎是软件还是网站,专业建设 验收 网站文章目录 一、类的定义1.1类定义的格式类的两种定义方法结构体#xff1a; 1.2访问限定符1.3类域 二、实例化2.1变量的声明和定义2.2类的大小计算空类的大小#xff08;面试#xff09;#xff1a; 三、this指针小考题 一、类的定义
1.1类定义的格式
使用class关键字 1.2访问限定符1.3类域 二、实例化2.1变量的声明和定义2.2类的大小计算空类的大小面试 三、this指针小考题 一、类的定义
1.1类定义的格式
使用class关键字定义类calssName是类名{}中为类的主体最后的分号 ;可别忘了加上。
类的名称就是类的类型。
类定义的函数属于inline内联函数但具体展开还是得看编译器的选择。
class calssName
{//成员函数 //成员变量
};
int main()
{tag st1;//类名就是类型
}成员变量member的特殊标识
在变量名前加上下划线在变慢名前加上字母m 类的两种定义方法
将函数的定义和声明放在类里面实现
这里使用class定义了一个日期类在main函数里声明了一个day1对象使用点操作符(.)、箭头操作符 (-)来访问类成员函数。
#include iostream
using std::cout;
using std::endl;class Data
{
public:void Init(int year 2024, int month 6, int day 6){_year year;_month month;_day day;}void print(){cout _year / _month / _day endl;}
private:int _year;int _month;int _day;
};
int main()
{Data day1;day1.Init(2024, 5, 20); day1.print();return 0;
}将函数声明放在类里面函数定义在类外面实现。
stack.h
#include iostream
class Stack
{
public:void Init(int capacity 4);void Push(int x);void Pop();int Top();int Empty();void Destry(){assert(_next);if (_next)free(_next);_next NULL;_top 0;_capacity 0;}
private:int _top;int _capacity;int* _next;
};stack.cpp
void Stack::Init(int capacity)
{_next (int*)malloc(sizeof(int) * capacity);_top 0;_capacity capacity;
}
void Stack::Push(int x)
{if (_top _capacity){int newcapacity _capacity 0 ? 4 : _capacity * 2;int* newNext (int*)realloc(_next, sizeof(int) * newcapacity);if (newNext NULL){perror(realloc fail);exit(1);}_next newNext;_capacity newcapacity;}_next[_top] x;
}void Stack::Pop()
{assert(_next _top 0);_top--;
}
int Stack::Top()
{assert(_next _top 0);return _next[_top - 1];
}
int Stack::Empty()
{return _top 0;
}结构体
在C中兼容C语言C编译器也支持struct关键字满足结构体的功能C不仅如此C还对它进行了升级也支持类的定义格式。
这里在C语言中定义一个链表的结构的。
struct ListNode
{int val;struct ListNode* next;
};而C兼容C语言又对结构进行升级在定义链表时可以直接省略struct关键字。
struct ListNode
{int val;ListNode* next;
};在结构体里和类一样还可以定义函数。下面使用C实现栈。
struct Stack
{
public:void Init(int capacity 4){_next (int*)malloc(sizeof(int) * capacity);_top 0;_capacity capacity;}void Push(int x){if (_top _capacity){int newcapacity _capacity 0 ? 4 : _capacity * 2;int* newNext (int*)realloc(_next, sizeof(int) * newcapacity);if (newNext NULL){perror(realloc fail);exit(1);}_next newNext;_capacity newcapacity;}_next[_top] x;}void Pop(){assert(_next _top 0);_top--;}int Top(){assert(_next _top 0);return _next[_top - 1];}int Empty(){return _top 0;}void Destry(){assert(_next);if (_next)free(_next);_next NULL;_top 0;_capacity 0;}
private:int _top;int _capacity;int* _next;
};
int main()
{Stack s1;s1.Init();s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);while (!s1.Empty()){cout s1.Top() endl;s1.Pop();}s1.Destry();return 0;
}可以发现使用C实现的栈与C语言没有过多的区别只是将栈的接口放在了结构体内部。 而在使用栈的结构体时并不像C语言那样需要频繁的传地址只需调用类成员函数即可以及在每一个函数名前省略了Stack栈的函数是在结构体内实现的属于Stack类域即使是其它地方的函数实现了Init、Push、Pop等功能那也是支持的。 调用栈的接口函数需使用 点操作符(.)。
1.2访问限定符
可以发现在上述实现类中使用了 pulic、private这两个是访问限定符用于限定对类成员访问的权限
C将对象的属性与方法封装在一起通过访问权限选择性的将接口提供给外部使用。public公有的被public修饰的成员在类外可以被访问private和protected修饰的成员不能在类外部直接访问它两的效果差不多常用 private两者之间的区别要在继承中才能体现出。访问限定符的作用域从限定符开始知道遇见下一个限定符结束或者遇见 }结束。class定义的成员没有使用访问限定符修饰class内默认使用 private修饰struct内默认使用 pulic修饰。 被限制在了类中而不能在外部使用相当于一种保护是不希望类中被锁上的成员被修改。一般不提供外部使用的成员变量使用 private和protected修饰提供外部使用的成员函数使用 pulic修饰。
1.3类域 类定义了一个新的作用域类域影响了编译器的查找规则类的所有成员都在类域中想要访问类域的成员使用 ::域作用限定符指出成员属于哪个类。 如同上述的将函数声明放在类里面函数定义在类外面实现。想要在类外实现类函数的定义就必须使用上::域作用限定符
使用 Stack::Stack指明了Init函数属于Stack类域
void Stack::Init(int capacity)
{_next (int*)malloc(sizeof(int) * capacity);_top 0;_capacity capacity;
}声明和定义分离需要指定类域
二、实例化
2.1变量的声明和定义
变量的声明是不占空间内存的只是告诉编译器存在这么个东西而定义是在内存中开辟空间。
以下变量是声明还是定义
class Data
{int _year;//声明int _month;//声明int _day;//声明
};
int val;//定义
int main()
{int n;//定义return 0;
}声明就相当于别人给你的口头承诺至于会不会实现那是另一回事只是他告诉你有这么个事而定义就相当于别人实实在在的帮你做完了事不局限于声明。 对象的实例化
对象实例化就是使用类类型创建变量的过程类的成员变量只是一个声明还没有为其开辟空间类是对对象的一个描述需要那些功能那些变量实现一个对象就会在类中一一实现。
就好比如一个塑料瓶子有了一个瓶子的模型需要大量生成塑料瓶的时候都会按照这个模型生产。类和对象也如同这样使用类将一个需要描述的对象的功能框架等一一在类中实现在需要使用的时候使用类创建一个对象。
同理一个类可以实例化多个对象就像一个冰棍的模型可以生产许多颗冰棍。实例化的对象会占据实际的物理空间存储数据。
2.2类的大小
该如何去计算一个类的大小它实际上与之前学习过的计算结构体大小规则一致。
结构体内存对齐的原则 结构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处上述两个结构体c1偏移量为0的原因 其它成员变量要对齐到对齐数的整数倍的地址处。 对齐数编译器默认的第一个对齐数 与 该成员变量大小的较小值。vs中默认—8linux中gcc 没有默认对齐数对齐数就是成员自身大小。 结构体中每个成员变量都有一个对齐数。 结构体总大小为最大对齐数结构体中最大对齐数的整数倍。 如果嵌套了结构体的情况嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处结构体的整体大小就是所有最大对齐数含嵌套结构体中成员中的对齐数的整数倍。
那咱就使用对齐规则尝试计算类的大小
class Data
{int _year;int _month;int _day;
};可以发现使用对齐规则计算后的大小为12个字节。 但类中是有函数的定义计算类的大小时需要将类成员函数也一起计算吗事实上并不需要。
#include iostream
using std::cout;
using std::endl;class Data
{
public:void Init(int year 2024, int month 6, int day 6){_year year;_month month;_day day;}void print(){cout _year / _month / _day endl;}
private:int _year;int _month;int _day;
};
int main()
{printf(%zd\n, sizeof(Data));return 0;
}可以发现在类中定义了两个类成员函数后计算的大小还是12个字节符合上述通过对齐规则计算后的结果。
类没有为类成员函数开辟内存空间那它们是存储在哪里。
类成员函数与类成员变量分开存储的。在计算类的大小是只考虑成员变量。使用同一个类实例化的对象对应每一个对象的成员变量来说都是存放在不同的空间中来管理数据而每一个对象的成员函数 例如Init都需调用相同的函数没有必要为每一个对象都开辟空间存放 Init函数这样会造成大量的空间浪费。
成员函数都有一块公共区域来存放对于每一个对象来说是公有的大家可以一块使用。 计算空类的大小面试
class S{};计算一个空类它的大小肯定不会为0
int main()
{S s;printf(%zd\n, sizeof(s));return 0;
}在main函数里定义了类S对象s它是通过类的大小开辟空间若一个空类的大小为0定义空类的时候编译器就会报错。
编译器给空类一个字节类唯一标识这个类的对象这一个字节不存储有效数据为一个占位符标识对象被实例化。
三、this指针 Date类中有Init和print两个成员函数函数体内没有为不同对象进行区别在使用day1、day2调用 Init函数时函数是如何区别是day1还是day2的。这里就通过C提供的隐含的this指针来解决。 编译器编译后类的成员函数默认都会在形参的第一个位置增加一个当前类类型的指针叫this指针。Date类中实现的Init函数原型为 void Init(Data* const this, int year int month, int day)this作为一个关键字存在不能显示的写在形参中编译器会自动完成。规定在函数内可以显示的用this指针可以给它加上也可以不加。不添加并不代表不存在this指针外界无法传入当前对象的地址给到被调用的成员函数使用this指针接受当前对象的地址this指针就会通过不同的地址去找到内存中对应的成员变量。this指针只能在成员函数内部使用因为它是作为一个成员函数的形参若是没有传递给当前对象地址的话那么它的指向是不确定的。this指针作为函数参数是不会存储在类中而是随着函数栈帧的开辟存放在栈区。
class Date
{
public://void Init(Data* const this, int year, int month, int day)void Init(int year, int month, int day){_year year;_month month;_day day;//this-_year year;//this-_month month;//this-_day day;}void print(){cout _year / _month / _day endl;}private:int _year;int _month;int _day;
};
int main()
{Date day1;Date day2;day1.Init(2024, 5, 20); day1.print();return 0;
}通过编译器调试可以发现的确存在this指针来接收了day1传递的地址。 小考题
下面程序编译运行后的结果是
A、编译报错 B、运行崩溃 C、正常运行
#includeiostream
using namespace std;
class A
{
public:void Print(){cout A::Print() endl;cout _a endl;}
private:int _a;
};
int main()
{A* p nullptr;p-Print();return 0;
}答案是B主函数内部不存在空指针的解引用Print不存在对象里面是在一块公共区域若 p-_a这样写就会出现空指针的解引用 _a是存在对象内部的就像结构体里空链表对结构体成员的访问。
成员函数的指针是在编译时确定的没有存放在对象中虽然写成了p-Print()但是没有解引用。
问题出在Print函数内Print函数的this指针接收了传递过来的空指针而又使用 this-_a对空指针进行了解引用从而造成程序崩溃。 文章转载自: http://www.morning.gbjxj.cn.gov.cn.gbjxj.cn http://www.morning.nknt.cn.gov.cn.nknt.cn http://www.morning.wdwfm.cn.gov.cn.wdwfm.cn http://www.morning.smry.cn.gov.cn.smry.cn http://www.morning.nsncq.cn.gov.cn.nsncq.cn http://www.morning.pgzgy.cn.gov.cn.pgzgy.cn http://www.morning.zstbc.cn.gov.cn.zstbc.cn http://www.morning.ampingdu.com.gov.cn.ampingdu.com http://www.morning.sgpny.cn.gov.cn.sgpny.cn http://www.morning.bmncq.cn.gov.cn.bmncq.cn http://www.morning.abgy8.com.gov.cn.abgy8.com http://www.morning.tqbqb.cn.gov.cn.tqbqb.cn http://www.morning.czxrg.cn.gov.cn.czxrg.cn http://www.morning.mmjqk.cn.gov.cn.mmjqk.cn http://www.morning.hbhnh.cn.gov.cn.hbhnh.cn http://www.morning.qpmmg.cn.gov.cn.qpmmg.cn http://www.morning.rzsxb.cn.gov.cn.rzsxb.cn http://www.morning.mrfbp.cn.gov.cn.mrfbp.cn http://www.morning.qgbfx.cn.gov.cn.qgbfx.cn http://www.morning.yslfn.cn.gov.cn.yslfn.cn http://www.morning.qmbtn.cn.gov.cn.qmbtn.cn http://www.morning.brwnd.cn.gov.cn.brwnd.cn http://www.morning.mflhr.cn.gov.cn.mflhr.cn http://www.morning.nrchx.cn.gov.cn.nrchx.cn http://www.morning.ljfjm.cn.gov.cn.ljfjm.cn http://www.morning.cnqff.cn.gov.cn.cnqff.cn http://www.morning.hmxb.cn.gov.cn.hmxb.cn http://www.morning.ylljn.cn.gov.cn.ylljn.cn http://www.morning.pangucheng.cn.gov.cn.pangucheng.cn http://www.morning.mqtzd.cn.gov.cn.mqtzd.cn http://www.morning.mqwnp.cn.gov.cn.mqwnp.cn http://www.morning.dtgjt.cn.gov.cn.dtgjt.cn http://www.morning.wqcbr.cn.gov.cn.wqcbr.cn http://www.morning.nqbpz.cn.gov.cn.nqbpz.cn http://www.morning.rhpgk.cn.gov.cn.rhpgk.cn http://www.morning.xkwyk.cn.gov.cn.xkwyk.cn http://www.morning.xlndf.cn.gov.cn.xlndf.cn http://www.morning.wtxdp.cn.gov.cn.wtxdp.cn http://www.morning.tpbhf.cn.gov.cn.tpbhf.cn http://www.morning.qztdz.cn.gov.cn.qztdz.cn http://www.morning.nkyqh.cn.gov.cn.nkyqh.cn http://www.morning.sfwd.cn.gov.cn.sfwd.cn http://www.morning.osshjj.cn.gov.cn.osshjj.cn http://www.morning.bpmtr.cn.gov.cn.bpmtr.cn http://www.morning.qnksk.cn.gov.cn.qnksk.cn http://www.morning.gmmxh.cn.gov.cn.gmmxh.cn http://www.morning.ydxwj.cn.gov.cn.ydxwj.cn http://www.morning.bqhlp.cn.gov.cn.bqhlp.cn http://www.morning.hrypl.cn.gov.cn.hrypl.cn http://www.morning.qyhcm.cn.gov.cn.qyhcm.cn http://www.morning.rrhfy.cn.gov.cn.rrhfy.cn http://www.morning.ptmgq.cn.gov.cn.ptmgq.cn http://www.morning.kkqgf.cn.gov.cn.kkqgf.cn http://www.morning.frcxx.cn.gov.cn.frcxx.cn http://www.morning.kqpxb.cn.gov.cn.kqpxb.cn http://www.morning.bfgbz.cn.gov.cn.bfgbz.cn http://www.morning.xpfwr.cn.gov.cn.xpfwr.cn http://www.morning.flncd.cn.gov.cn.flncd.cn http://www.morning.smrkf.cn.gov.cn.smrkf.cn http://www.morning.langlaitech.cn.gov.cn.langlaitech.cn http://www.morning.rrhfy.cn.gov.cn.rrhfy.cn http://www.morning.pfntr.cn.gov.cn.pfntr.cn http://www.morning.pjtnk.cn.gov.cn.pjtnk.cn http://www.morning.qxljc.cn.gov.cn.qxljc.cn http://www.morning.dgckn.cn.gov.cn.dgckn.cn http://www.morning.tmnyj.cn.gov.cn.tmnyj.cn http://www.morning.kpcjl.cn.gov.cn.kpcjl.cn http://www.morning.prlgn.cn.gov.cn.prlgn.cn http://www.morning.cbnlg.cn.gov.cn.cbnlg.cn http://www.morning.jthjr.cn.gov.cn.jthjr.cn http://www.morning.jcrfm.cn.gov.cn.jcrfm.cn http://www.morning.grryh.cn.gov.cn.grryh.cn http://www.morning.mnrqq.cn.gov.cn.mnrqq.cn http://www.morning.kwnnx.cn.gov.cn.kwnnx.cn http://www.morning.txqsm.cn.gov.cn.txqsm.cn http://www.morning.ghslr.cn.gov.cn.ghslr.cn http://www.morning.mfmx.cn.gov.cn.mfmx.cn http://www.morning.pzdxg.cn.gov.cn.pzdxg.cn http://www.morning.ycmpk.cn.gov.cn.ycmpk.cn http://www.morning.lwqst.cn.gov.cn.lwqst.cn