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
运行结果
复制代码

  简单总结一下,函数间传递对象有三种方式,分别是值传递、引用传递和指针传递。如果不需要修改主调函数的对象值,而只是读取其中的数据,那么程序员可以主动的将被调函数的对象形参定义成常对象、常引用或指向常对象的指针。

 

posted @   KylinZhuang  阅读(135)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示