本篇文章将介绍对象数组,对象的动态分配以及对象在函数中的应用。

一、对象数组

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++对象的应用的更多相关文章

  1. 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑

    阅读目录 前言 场景1的思考 场景2的思考 避坑方式 实践 结语 一.前言 在上一篇中(如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成),有一行注释的代码: public interfa ...

  2. javascript中的Array对象 —— 数组的合并、转换、迭代、排序、堆栈

    Array 是javascript中经常用到的数据类型.javascript 的数组其他语言中数组的最大的区别是其每个数组项都可以保存任何类型的数据.本文主要讨论javascript中数组的声明.转换 ...

  3. 探究javascript对象和数组的异同,及函数变量缓存技巧

    javascript中最经典也最受非议的一句话就是:javascript中一切皆是对象.这篇重点要提到的,就是任何jser都不陌生的Object和Array. 有段时间曾经很诧异,到底两种数据类型用来 ...

  4. Asp.Net WebApi核心对象解析(下篇)

    在接着写Asp.Net WebApi核心对象解析(下篇)之前,还是一如既往的扯扯淡,元旦刚过,整个人还是处于晕的状态,一大早就来处理系统BUG,简直是坑爹(好在没让我元旦赶过来该BUG),队友挖的坑, ...

  5. JS核心系列:浅谈原型对象和原型链

    在Javascript中,万物皆对象,但对象也有区别,大致可以分为两类,即:普通对象(Object)和函数对象(Function). 一般而言,通过new Function产生的对象是函数对象,其他对 ...

  6. Chrome出了个小bug:论如何在Chrome下劫持原生只读对象

    Chrome出了个小bug:论如何在Chrome下劫持原生只读对象 概述 众所周知,虽然JavaScript是个很灵活的语言,浏览器里很多原生的方法都可以随意覆盖或者重写,比如alert.但是为了保证 ...

  7. XStream将java对象转换为xml时,对象字段中的下划线“_”,转换后变成了两个的解决办法

            在前几天的一个项目中,由于数据库字段的命名原因 其中有两项:一项叫做"市场价格"一项叫做"商店价格" 为了便于区分,遂分别将其命名为market ...

  8. ASP.NET内置对象的总结

    1. Response对象可形象的称之为响应对象,用于将数据从服务器发送回浏览器. 实例源码:链接: http://pan.baidu.com/s/1dDCKQ8x 密码: ihq0  2. Requ ...

  9. ADO.NET对象的详解

    1. Connection 类 和数据库交互,必须连接它.连接帮助指明数据库服务器.数据库名字.用户名.密码,和连接数据库所需要的其它参数.Connection对象会被Command对象使用,这样就能 ...

  10. 对Castle Windsor的Resolve方法的解析时new对象的探讨

    依赖注入框架Castle Windsor从容器里解析一个实例时(也就是调用Resolve方法),是通过调用待解析对象的构造函数new一个对象并返回,那么问题是:它是调用哪个构造函数呢? 无参的构造函数 ...

随机推荐

  1. 同时将代码备份到Gitee和GitHub

    同时将代码备份到Gitee和GitHub 如何将GitHub项目一步导入Gitee 如何保持Gitee和GitHub同步更新 如何将GitHub项目一步导入Gitee 方法一: 登陆 Gitee 账号 ...

  2. for & while &迭代器

    for (int i = 0; i < 10; i++) { System.out.println("hello"); } int a=100; for (;a<110 ...

  3. JQ的is()

     is():根据选择器.元素或jQuery对象来检测匹配元素集合, 如果这些元素中至少有一个元素匹配给定的参数,则返回true. <!DOCTYPE html> <html lang ...

  4. Asp.Net Core 7 preview 4 重磅新特性--限流中间件

    前言 限流是应对流量暴增或某些用户恶意攻击等场景的重要手段之一,然而微软官方从未支持这一重要特性,AspNetCoreRateLimit这一第三方库限流库一般作为首选使用,然而其配置参数过于繁多,对使 ...

  5. 无线:SSID

    BSSID,SSID,ESSID区别   SSID(Service Set Identifier)   SSID,AP唯一的ID码,许多人认为可以将SSID写成ESSID,其实不然,SSID是个笼统的 ...

  6. Python <算法思想集结>之初窥基础算法

    1. 前言 数据结构和算法是程序的 2 大基础结构,如果说数据是程序的汽油,算法则就是程序的发动机. 什么是数据结构? 指数据在计算机中的存储方式,数据的存储方式会影响到获取数据的便利性. 现实生活中 ...

  7. Codeforces Round #773 (Div. 2)

    这一场打的非常一般,不过把D想出来了(当然只剩10min没有写出来). A.Hard Way 题意:(很怪的题,我读题读半天)给你一个三角形(端点都在整数点上),问从x轴往上划线(不一定垂直)画不到的 ...

  8. React中使用react-player 播放视频或直播

    业务中需要播放视频,寻来寻去,找到了react-player 初次点击,甚是眼熟,思来想去,竟是钉钉同款 如果使用react框架 先安装 npm install --save video-react ...

  9. C语言- 基础数据结构和算法 - 栈的顺序存储

    听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/video/BV1vE411f7Jh?p=1 喜欢的朋友 ...

  10. 《SQL Server基础——SQL语句》

    SQL Server基础--SQL语句       一.创建和删除数据库: 1.创建数据库(默认化初始值) 格式: CREATE DATABASE 数据库名称 例如: CREATE DATABASE ...