C++对象的应用
本篇文章将介绍对象数组,对象的动态分配以及对象在函数中的应用。
一、对象数组
1、对象数组的定义和初始化
定义对象数组与定义普通数组的语法形式基本相同。如定义一个Square obj[3];表示一个正方形类的对象数组,数组元素为三个。将该数组初始化:Square[3]={Square(2),Square(3),Square(4)};
对象初始化的表示形式是“类名(参数列表)”。计算机在执行对象数组定义语句时,数组中有多少元素,就会调用多少次构造函数。
2、对象数组的访问
对象数组的每个元素都是一个对象,都有各自的成员。可以访问各种对象元素的公有成员,访问形式:对象数组名[下标].公有成员名; 当然也可以通过指针访问:Square *p = obj;p->Area();
3、对象数组的析构
销毁对象数组,就是逐个销毁其中的所有对象元素。换句话说,计算机销毁对象数组时,数组中有多少个元素,就会调用多少次析构函数。
二、对象的动态分配
C++可以使用内存分配方法定义对象或对象数组。new运算符动态分配内存,内存使用完之后通过delete运算符即时释放,提高内存利用率。内存的动态分配、访问以及释放需要通过指针变量才能实现。
1、单个对象的分配与释放
首先预定义一个类类型指针用来保存分配空间的首地址,后续访问内存单元时将使用该对象指针进行间接访问。动态分配类的对象时会自动调用该类的构造函数,删除对象时自动调用类的析构函数。
方法一: Square *p; p = new Square; //分配一个类Square的对象,用p保存所分配内存额首地址 delete p; 方法二: Square *p; p = new Square(2);delete p; // 分配一个类Square的对象,并将其边长初始化为2 方法三: Square *p = new Square(2);delete p;
2、对象数组的分配与释放
动态分配对象数组时,数组中有多少个元素就会调用多少次析构函数。删除对象数组时,数组中有多少个元素就会调用多少析构函数。
Square *p; //预定义指向对象数组首地址的指针
p =new Square[3];//分配一堆对象数组,包含3个元素
p[0].a=2; cout<<p[0].Area();
(p+1)->a=3;cout<<(p+1)->Area();//通过指针访问数组元素的成员 delete []p;//释放p 所指向的一组对象
三、对象作为函数的形参
与变量一样,函数间传递对象时也存在值传递、引用传递和指针传递。
1、值传递与常对象
对象在函数间的值传递实际上时重构了一个对象形参,将实参对象复制到形参对象中。对于只读不改的对象可以定义为常对象。常对象在定义时必须初始化,定义后不能在修改其数据成员。
2、引用传递与常引用
引用传递将被调函数的对象形参定义成主调函数中对象实参的引用,被调函数通过该引用间接访问主调函数中的对象。被调函数对引用的修改都会影响主调函数中实参对象的值。为了避免这种传递带来的互相影响,我们可以将被调函数的形参定义为常引用。常引用定义后,被调函数任何想要通过其形参修改主调函数实参值的操作都会提示错误,不被允许。
注意:引用传递时函数间传递对象最常用的方式,原因在它不需要额外申请空间,可以互相传值,还可以通过常引用避免形参改变影响实参。
3、指针传递与指向常对象的指针
指针传递就是将主调函数中的对象实参的内存地址传递给被调函数的对象指针形参,被调函数通过该地址间接访问主调函数的对象。和引用传递一样形参同样可以改变实参,为了避免这样传递带来的互相影响,可以将被调函数的形参定义为指向常对象的指针。定义成指向常对像的指针后,被调函数任何想要通过其指向常对象的指针形参修改主调函数实参值的操作都会提示错误,不被允许。
下面通过一个实例来介绍这六种对象传参方法:


#include<iostream>
using namespace std;
//类定义
class Square
{
public:
double a; //数据成员a表示:正方形边长
double Area() //内联函数Area():求正方形面积
{
return(a*a);
}
Square(double x = 0) //带默认形参值的构造函数
{
a=x;
}
};
//求正方形对象s的内切圆面积
double InnerCircleArea1(Square s) //值传递
{
s.a=4;
double r = s.a/2;
return (3.14*r*r);
} double InnerCircleArea2( const Square s) //常对像值传递
{
//s.a=4; 形参为常对象,不得修改常对象的成员值
double r = s.a/2;
return (3.14*r*r);
}
double InnerCircleArea3(Square &s) //引用传递
{
s.a=4;
double r = s.a/2;
return (3.14*r*r);
}
double InnerCircleArea4(const Square &s) //常引用对象传递
{
//s.a=4; 形参为常引用对象,不得修改常引用对象的成员值
double r = s.a/2;
return (3.14*r*r);
}
double InnerCircleArea5(Square *s) //指针传递
{
s->a=6;
double r = s->a/2;
return (3.14*r*r);
}
double InnerCircleArea6(const Square *s) //指向常对象的指针传递
{
//s->a=6; 形参为指向常对象的指针,不得通过常对象指针修改所指对象的成员值
double r = s->a/2;
return (3.14*r*r);
}
int main()
{
Square obj(2);
cout <<"值传递: "<< InnerCircleArea1(obj) << endl; //初始边长为2,函数内修改a为4
cout <<"常量值传递:"<< InnerCircleArea2(obj) << endl; //初始边长为2,函数内修改a为4,语法错误
cout <<"引用传递: "<< InnerCircleArea3(obj) << endl; //初始边长为2,函数内修改a为4
cout <<"常引用传递:"<< InnerCircleArea4(obj) << endl; //初始边长为2,函数内修改a为4,语法错误
cout <<"指针传递: "<< InnerCircleArea5(&obj) << endl; //初始边长为2,函数内修改a为6
cout <<"常指针传递:"<< InnerCircleArea6(&obj) << endl; //初始边长为2,函数内修改a为6,语法错误 return 0;
} 对象函数传递示例
函数中的对象传递

#include<iostream>
using namespace std;
//类定义
class Square
{
public:
double a; //数据成员a表示:正方形边长
double Area() //内联函数Area():求正方形面积
{
return(a*a);
}
Square(double x = 0) //带默认形参值的构造函数
{
a=x;
}
};
//求正方形对象s的内切圆面积
double InnerCircleArea1(Square s) //值传递
{
s.a=4;
double r = s.a/2;
return (3.14*r*r);
} double InnerCircleArea2( const Square s) //常对像值传递
{
//s.a=4; 形参为常对象,不得修改常对象的成员值
double r = s.a/2;
return (3.14*r*r);
}
double InnerCircleArea3(Square &s) //引用传递
{
s.a=4;
double r = s.a/2;
return (3.14*r*r);
}
double InnerCircleArea4(const Square &s) //常引用对象传递
{
//s.a=4; 形参为常引用对象,不得修改常引用对象的成员值
double r = s.a/2;
return (3.14*r*r);
}
double InnerCircleArea5(Square *s) //指针传递
{
s->a=6;
double r = s->a/2;
return (3.14*r*r);
}
double InnerCircleArea6(const Square *s) //指向常对象的指针传递
{
//s->a=6; 形参为指向常对象的指针,不得修改常向常对象指针所指对象的成员值
double r = s->a/2;
return (3.14*r*r);
}
int main()
{
Square obj(2);
cout <<"值传递: "<< InnerCircleArea1(obj) << endl; //初始边长为2,函数内修改a为4
cout <<"常量值传递:"<< InnerCircleArea2(obj) << endl; //初始边长为2,函数内修改a为4,语法错误
cout <<"引用传递: "<< InnerCircleArea3(obj) << endl; //初始边长为2,函数内修改a为4
cout <<"常引用传递:"<< InnerCircleArea4(obj) << endl; //初始边长为2,函数内修改a为4,语法错误
cout <<"指针传递: "<< InnerCircleArea5(&obj) << endl; //初始边长为2,函数内修改a为6
cout <<"常指针传递:"<< InnerCircleArea6(&obj) << endl; //初始边长为2,函数内修改a为6,语法错误 return 0;
}
运行结果如下


值传递: 12.56
常量值传递:3.14
引用传递: 12.56
常引用传递:12.56
指针传递: 28.26
常指针传递:28.26
运行结果
简单总结一下,函数间传递对象有三种方式,分别是值传递、引用传递和指针传递。如果不需要修改主调函数的对象值,而只是读取其中的数据,那么程序员可以主动的将被调函数的对象形参定义成常对象、常引用或指向常对象的指针。
C++对象的应用的更多相关文章
- 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑
阅读目录 前言 场景1的思考 场景2的思考 避坑方式 实践 结语 一.前言 在上一篇中(如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成),有一行注释的代码: public interfa ...
- javascript中的Array对象 —— 数组的合并、转换、迭代、排序、堆栈
Array 是javascript中经常用到的数据类型.javascript 的数组其他语言中数组的最大的区别是其每个数组项都可以保存任何类型的数据.本文主要讨论javascript中数组的声明.转换 ...
- 探究javascript对象和数组的异同,及函数变量缓存技巧
javascript中最经典也最受非议的一句话就是:javascript中一切皆是对象.这篇重点要提到的,就是任何jser都不陌生的Object和Array. 有段时间曾经很诧异,到底两种数据类型用来 ...
- Asp.Net WebApi核心对象解析(下篇)
在接着写Asp.Net WebApi核心对象解析(下篇)之前,还是一如既往的扯扯淡,元旦刚过,整个人还是处于晕的状态,一大早就来处理系统BUG,简直是坑爹(好在没让我元旦赶过来该BUG),队友挖的坑, ...
- JS核心系列:浅谈原型对象和原型链
在Javascript中,万物皆对象,但对象也有区别,大致可以分为两类,即:普通对象(Object)和函数对象(Function). 一般而言,通过new Function产生的对象是函数对象,其他对 ...
- Chrome出了个小bug:论如何在Chrome下劫持原生只读对象
Chrome出了个小bug:论如何在Chrome下劫持原生只读对象 概述 众所周知,虽然JavaScript是个很灵活的语言,浏览器里很多原生的方法都可以随意覆盖或者重写,比如alert.但是为了保证 ...
- XStream将java对象转换为xml时,对象字段中的下划线“_”,转换后变成了两个的解决办法
在前几天的一个项目中,由于数据库字段的命名原因 其中有两项:一项叫做"市场价格"一项叫做"商店价格" 为了便于区分,遂分别将其命名为market ...
- ASP.NET内置对象的总结
1. Response对象可形象的称之为响应对象,用于将数据从服务器发送回浏览器. 实例源码:链接: http://pan.baidu.com/s/1dDCKQ8x 密码: ihq0 2. Requ ...
- ADO.NET对象的详解
1. Connection 类 和数据库交互,必须连接它.连接帮助指明数据库服务器.数据库名字.用户名.密码,和连接数据库所需要的其它参数.Connection对象会被Command对象使用,这样就能 ...
- 对Castle Windsor的Resolve方法的解析时new对象的探讨
依赖注入框架Castle Windsor从容器里解析一个实例时(也就是调用Resolve方法),是通过调用待解析对象的构造函数new一个对象并返回,那么问题是:它是调用哪个构造函数呢? 无参的构造函数 ...
随机推荐
- ONNXRuntime学习笔记(三)
接上一篇完成的pytorch模型训练结果,模型结构为ResNet18+fc,参数量约为11M,最终测试集Acc达到94.83%.接下来有分两个部分:导出onnx和使用onnxruntime推理. 一. ...
- Lab1:练习四——分析bootloader加载ELF格式的OS的过程
练习四:分析bootloader加载ELF格式的OS的过程. 1.题目要求 通过阅读bootmain.c,了解bootloader如何加载ELF文件.通过分析源代码和通过qemu来运行并调试bootl ...
- Unity实现简单的对象池
一.简介 先说说为什么要使用对象池 在Unity游戏运行时,经常需要生成一些物体,例如子弹.敌人等.虽然Unity中有Instantiate()方法可以使用,但是在某些情况下并不高效.特别是对于那些需 ...
- 6┃音视频直播系统之 WebRTC 核心驱动SDP规范协商
一.什么是SDP SDP(Session Description Protocal)其实就是当数据过来时候,告诉数据自己这里支持的解码方式.传输协议等等,这样数据才能根据正确的方式进行解码使用 SDP ...
- drools执行完某个规则后终止别的规则执行
目录 1.背景 2.需求 3.实现方案 1.通过Fact判断 2.通过全局变量判断 3.通过halt方法 4.实现上述需求 4.1 drl 文件编写 4.2 运行结果 5.完整代码 1.背景 在我们开 ...
- 【可视化分析案例】用python分析B站Top100排行榜数据
一.数据源 之前,我分享过一期爬虫,用python爬取Top100排行榜: 最终数据结果,是这样的: 在此数据基础上,做python可视化分析. 二.数据读取 首先,读取数据源: # 读取csv数据 ...
- XDEBUG 选项
到官网 http://www.xdebug.com/download.php 下载 找到对应PHP版本的 Xdebug ,后面带 TS 的为线程安全,本机环境为 win7 64 + php-5.5.1 ...
- 软件成分分析(SCA)完全指南
上一篇文章中,我们讨论了 DAST 的概念.重要性及其工作原理.那在开发过程中如何查找开源软件包中的漏洞并学习如何修复?本指南带你一起了解 SCA 工具及其最佳实践. 如今,绝大多数代码驱动的应用程序 ...
- spring源码解析:元注解功能的实现
前言 众所周知,spring 从 2.5 版本以后开始支持使用注解代替繁琐的 xml 配置,到了 springboot 更是全面拥抱了注解式配置.平时在使用的时候,点开一些常见的等注解,会发现往往在一 ...
- jetbrains 系列产品无限试用
无限试用插件 在线安装 需要添加第三方插件仓库地址 设置 -- Manage Plugins Reposition... -- + https://plugins.zhile.io plugins 中 ...