4.5 引用与复制构造函数

来源:互联网 发布:豆瓣评分知乎 编辑:程序博客网 时间:2024/04/29 03:42

引用

◆ 1、什么是引用?
引用又称别名(alias),是一种非常特殊的数据类型。它不是定义一个新的变量,而是给一个已经定义的变量重新起一个别名,也就是C++系统不为引用类型变量分配内存空间。引用主要用于函数之间的数据传递。

引用定义的格式为:
    类型 &引用变量名=已定义过的变量名;

例如:
    double number ;
    double &newnum=number ;
newnum是新定义的引用类型变量,它是变量number的别名,两个变量代表同一块内存。

◆ 2、【例4.3】使用一个函数交换两个数据。查看动画演示
#include<iostream.h>
void swap(double & d1,double & d2) //d1和d2是引用型变量
{
       double temp ;
       temp=d1 ;
       d1=d2 ;
       d2=temp ;
}

void main(void)
{
       double x , y ;
       cout<<"请输入x和y的值"<<'\n';
       cin>>x>>y ;
       swap(x,y) ;
       cout<<"x="<<x<<'\t'<<"y="<<y<<'\n';
}

◆ 3、引用可以作为函数的返回值
一般函数返回值时,要生成一个临时变量作为返回值的拷贝,而用引用作为返回值时,不生成值的拷贝。

【例4.4】采用不同返回方式的求正方形面积函数的比较。
#include<iostream>
using namespace std;
double temp;
double fsqr1(double a){
    temp=a*a ; return temp;
}
double & fsqr2(double a){
    temp=a*a ; return temp;
}
int main(){
    double x=fsqr1(5.5);//第一种情况
    double y=fsqr2(5.5);//第二种情况
    cout<<"x="<<x<<'\t'<<"y="<<y<<endl;
    return 0;
}

几点注意:
  • 对数组只能引用数组元素,不能引用数组(数组名本身为地址)。
  • 不能定义引用的引用(引用也是地址),所以当函数的参数为引用时,引用不能作实参。

复制构造函数

在建立新对象时可用同一类的另一个对象来初始化该对象,例如,得到一个和“商品甲”属性相同的“商品乙”,当然二者的名字(对象名称)不同。这时所用的构造函数称为复制构造函数(Copy Constructor)。

◆ 1、什么是复制构造函数?
对于CGoods类,可以定义复制构造函数为:
CGoods (CGoods & cgd)
{
       StrCpy (Name , cgd.Name);
       Price= cgd.price;
       Amount=cgd.Amount;
       Total_value=cgd.Total_value;
};

这里必须注意复制构造函数的参数——同类(class)的对象采用的是引用的方式。如果把一个真实的类对象作为参数传递到复制构造函数,会引起无穷递归 。所以必须将复制构造函数的参数定义为一个类的对象的引用。

◆ 2、 若用户没有定义复制构造函数,系统会自动提供,称为缺省的按成员语义支持的复制构造函数,每个成员的值被依次拷贝,亦称为缺省的按成员初始化
按成员作复制是通过依次拷贝每个数据成员实现的,而不是对整个类对象按位拷贝。赋值运算符“=”称缺省的按成员拷贝赋值操作符,同类对象之间可以用“=”直接拷贝 。

◆ 3、在某些情况下,缺省的按成员复制对类与对象的安全性和处理的正确性还不够,这时就要求类的设计者提供专门的复制构造函数(Copy Constructor)和复制赋值操作符'='(Copy Assignment Operator)的定义。

◆ 4、复制构造函数的使用
例如以下:对象cary和对象carz的产生就是通过系统自动调用复制构造函数的,他们的属性等和carx完全相同:
    CGoods carx(“夏利2000”,30,98000.0);
    CGoods cary=carx,carz(carx);

◆ 5、复制构造函数并不只是在同类的一个对象去初始化该类的另一个对象时使用,它还在另二个方面使用:
  • 当函数的形参是类的对象,调用函数时,形参与实参结合时使用。这时要在内存新建立一个局部对象,并把实参拷贝到新的对象中。要调用拷贝构造函数;
  • 当函数的返回值是类对象时使用。理由,是要先建立一个临时对象,再返回调用者。为什么不直接用要返回的局部对象呢?因为局部对象在离开建立它的函数时就消亡了,所以编译系统会在调用函数的表达式中创建一个临时对象,该临时对象的生存周期只在函数调用处的表达式中。所谓return X,实际上是调用拷贝构造函数把X拷入临时对象。如果返回的是变量,处理过程类似,只是不调用构造函数。

成员对象与构造函数

◆ 1、什么是成员对象?
【例4.6】含有成员对象的类:
class student
{
public:
       class studentID //学号类studentID的定义开始
       {
              long value;
       public:
              studentID(long id=0)
              {
                     value=id;
                     cout<<value<<endl;
              }
              ~studentID()
              {
                     cout<<"删除"<<value<<endl;
              }
       }; //学号类studentID的定义结束,注意分号

private:
       char name[20];
       studentID id;
       //id是一个成员对象,它既是类student的成员,又是类studentID型的对象

public:
       student (char* sname=“no name”,long sid=0):id(sid)
       //关注id的构造!
       //sname 现暂看作字符串,char*是指向字符的指针类型
       {
              cout<<“学生名:”<<sname<<endl;
              strcpy(name,sname);
       }

}; //类student定义结束

◆ 2、student型的对象构造时,其中的成员对象id如何产生?
上面代码中,student类的构造函数头后半部分语句 :id(sid) 即可使系统调用对象id所属类studentID的构造函数,以产生id。

◆ 3、C++中对含成员对象的类对象的构造函数有特殊的格式:
    类名::构造函数名(参数总表):成员对象1(参数表1),成员对象2(参数表2),……成员对象n(参数表n)
    {……}


◆ 4、先调用哪个对象成员的构造函数,取决与它们在类中说明的顺序;对象产生时,先初始化对象成员,后初始化其他成员;对象撤销时,相反。
0 0
原创粉丝点击