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

c++类和对象(上)

类是c++的独特形式,可以在类中包括函数进行。

对象是通过类创建的一个个变量。

类的存储

类中的每一个

类中的函数,不存入类的内存。如图定义了一个类,有一个int类型,4字节。一个函数无内存。

类的存储的大小还要看对齐数

对齐数=(对齐数默认的数)和(类内的成员变量的大小)的较小值,每一个类成员都有一个对齐数。

内存大小为(成员变量的对齐数最大值)的整数倍

vs(对齐数)默认是8

如果是类嵌套,取嵌套中的最大对齐数。

原因1:平台问题,有些硬件平台只能取特定类型的数据。cpu不能从任意位置开始读只能从整数倍开始,不能读任意字节只能读固定字节。如下图4的整数倍开始读,一次性读取4字节。

2:性能原因,处理器处理未对齐的需要两次,对齐的只需要1次。

如果定义的类没有内容,内存为1字节证明存在。成员变量没有内容也会给1字节证明有这个成员。

c++,定义了一个this指针作为。隐藏在类中的函数的一个参数,指向自身,不可修改。

#include<iostream> #include<string> using namespace std; class jst{ public: int a; //void print(jst* const this) void print( ){ cout<<a<<endl; } }; class st1{ }; class st2{ st1 a; st1 b; }; int main(){ jst s; s.a=10; s.print(); //s.print(&s); cout<<sizeof(st1)<<endl; cout<<sizeof(st2)<<endl; return 0; }

类中直接访问用.,通过指针访问用->。

不能自己显示的写this指针。

可以在函数体内可以用。

this指针存储到栈中。

#include<iostream> #include<string> using namespace std; class jst{ public: void print(){ cout<<"666"<<endl; } }; int main(){ jst* s=nullptr; s->print(); return 0; }

可以正常运行,因为函数没有存在类中,调用后只传了s的地址。

在c++的类中,可以把不同的数据封装到不同的区,防止胡乱调用。如下面的代码,只能通过jst中的函数进行操作。实现不能直接操作s.a,必须间接操作。

#include<iostream> #include<string> using namespace std; class jst{ public: void push(int n,int m){ a[n]=m; } void print(int n){ cout<<a[n]; } private: int a[4]; }; int main(){ jst s; s.push(0,1); s.print(0); return 0; }

默认成员函数

在类中如果你没有创建,编译器自动生成的函数,还有两个移动构造,移动赋值。

初始化和清理。构造函数初始化工作。

析构函数清理工作。

拷贝复制, 拷贝构造是使用同类对象初始化创建对象。

赋值重载,把一个对象赋值给另一个对象。

取地址重载 普通对象和const对象的取址

构造函数

函数名和类名相同。

无返回值。不需要写void。

对象创建时自动调用。

构造函数可以重载。

无参

#include<iostream> #include<string> using namespace std; class jst{ public: jst(){ a[0]=1; a[1]=2; a[2]=3; a[3]=4; } void print(){ cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<" "<<a[3]; } private: int a[4]; }; int main(){ jst s; s.print(); return 0; }

带参,在创建时跟在创建末尾。

#include<iostream> #include<string> using namespace std; class jst{ public: jst(int q,int w,int e,int r){ a[0]=q; a[1]=w; a[2]=e; a[3]=r; } void print(){ cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<" "<<a[3]; } private: int a[4]; }; int main(){ jst s(2,3,4,5); s.print(); return 0; }

全缺省。可以自己初始。

#include<iostream> #include<string> using namespace std; class jst{ public: jst(int q=1,int w=2,int e=3,int r=4){ a[0]=q; a[1]=w; a[2]=e; a[3]=r; } void print(){ cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<" "<<a[3]; } private: int a[4]; }; int main(){ jst s(0,0); s.print(); return 0; }

默认构造是不用传参的就是默认构造,包括无参和全缺省。

默认生成2个中的一个.

3个构造函数只能存在一个。

看编译器生成无参函数和全缺省函数。

对于自定义的类型会调用自定义的构造函数。

#include<iostream> #include<string> using namespace std; class jst{ public: jst(){ a[0]=1;a[1]=2;a[2]=3;a[3]=4; } void print(){ cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<" "<<a[3]<<endl; } private: int a[4]; }; class jst2{ public: void print(){ a1.print(); a2.print(); } private: jst a1; jst a2; }; int main(){ jst2 s; s.print(); return 0; }

一般构造函数自己写。

析构函数

析构函数名是在类名前加上字符~;

无参无返回值。

一个类只有一个析构。

对象结束会自动调用。

如果不写会自动生成。

对于自定义,也会调用它的析构。

#include<iostream> #include<string> #include<cstdlib> using namespace std; class jst{ public: jst(){ a=(int*)malloc(sizeof(int)*4); a[0]=1;a[1]=2;a[2]=3;a[3]=4; } ~jst(){ cout<<"0"<<endl; free(a); } void print(){ cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<" "<<a[3]<<endl; } private: int* a; }; class jst1{ public: jst1(){ a=(int*)malloc(sizeof(int)*4); a[0]=1;a[1]=2;a[2]=3;a[3]=4; } ~jst1(){ cout<<"1"<<endl; free(a); } void print(){ cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<" "<<a[3]<<endl; } private: int* a; }; class jst2{ public: void print(){ a1.print(); a2.print(); } private: jst a1; jst1 a2; }; int main(){ jst2 s; s.print(); return 0; }

后定义的先析构。

对于自定义函数总会使用自定义的析构。

没有申请资源的类可以不写析构。

显示写析构,也会自动调用默认析构。

运算符重载

运算符在类中可以重载。

#include<iostream> #include<string> #include<cstdlib> using namespace std; class Data{ public: Data(int year=1,int yue=1,int day=1 ){ _year=year; _yue=yue; _day=day; } int que(int n){ if(n>0&&n<4){ if(n==1) return _year; else if(n==2) return _yue; else return _day; } } private: int _year;int _yue;int _day; }; bool operator==(Data d1,Data d2){ return d1.que(1)==d2.que(1)&&\ d1.que(2)==d2.que(2)&&\ d1.que(3)==d2.que(3); }; int main(){ Data t1(2,2,2); Data t2; Data t3; if(t1==t2) cout<<"666"<<endl; else cout<<"999"<<endl; if(t3==t2) cout<<"666"<<endl; return 0; } 或者 class Data{ public: Data(int year=1,int yue=1,int day=1 ){ _year=year; _yue=yue; _day=day; } int que(int n){ if(n>0&&n<4){ if(n==1) return _year; else if(n==2) return _yue; else return _day; } } bool operator==(Data d2){ return _year==d2._year&&\ _yue==d2._yue&&\ _day==d2._day; }; private: int _year;int _yue;int _day; };

第二种方式使用的this指针,t1.opertaor==(t2),可以省略为t1==t2。

只能对于已有的操作符重载,不能重新创建一个全新的操作符。

http://www.jsqmd.com/news/84394/

相关文章:

  • 38、Python编程:回调函数、包管理与系统操作全解析
  • 深度学习的进化之路:从感知机到通用智能的曙光
  • python装饰器
  • Oracle、PL\SQL安装配置
  • Part 01|在多个项目之后,我开始对“现成商城系统”产生怀疑
  • 目标检测系列之YOLOv4——速度与精度的平衡
  • 分布式训练知识
  • 第一章——办公自动化之邮件批量发送:高效沟通,一键搞定
  • B站的视频怎么下载到电脑?
  • Part 02|我为什么开始自己做一套商城系统
  • 《AI元人文构想:元协议、行为重塑与文明免疫系统》一篇技术或伦理的论述与一份关于智能时代文明如何存续与发展的奠基性宣言
  • CAIE认证:一次关于AI认知与思维升级的个人记录
  • 21.数据库连接池
  • 常见API(补充)
  • 《Python实战小课:数据分析场景——解锁数据洞察之力》导读
  • 34、Python 数据持久化与序列化:从简单到关系型的全面解析
  • 放过自己,也放过你的领导
  • Part 03|当客户真的要交付时,我最先考虑的不是技术
  • 设计模式复习1
  • 我对防抖(Debounce)的一点理解与实践:从基础到立即执行
  • [网鼎杯 2020 青龙组]AreUSerialz(个人记录写题笔记,含PHP反序列化的原理、漏洞成因以及利用技巧)
  • PINN学习(三)—— 发现方程问题的解决
  • 当AI成为同事:HR的“战斗力”正在被重新定义
  • 【安卓aosp】编译报错 killed 如果处理
  • Comsol Multiphysics数值模拟
  • Windows11中使用VS2022编译运行libevent网络库
  • 不止于智能:GPT-5.1 发布,更温暖、更好聊的 ChatGPT 来啦!
  • 战网注册后显示无法登录
  • Creed —— 血液特效与敌人伤害
  • 生成式搜索优化服务商排行