美文网首页
C++ 构造函数与析构函数

C++ 构造函数与析构函数

作者: 代码人生ll | 来源:发表于2019-03-20 10:26 被阅读0次

    构造函数与析构函数

    OOP第二课

    1、构造函数

    1.1 构造函数具有一些特殊的性质

    1.2 定义构造函数的一般形式

    1.3 利用构造函数创建对象

    2、成员初始化表

    3、缺省参数的构造函数

    4、重载构造函数

    5、拷贝构造函数

    5.1 自定义拷贝构造函数

    5.2 缺省的拷贝构造函数

    5.3 调用拷贝构造函数的三种情况

    5.4 浅拷贝和深拷贝

    6、析构函数

    7、调用构造函数和析构函数的顺序

    8、对象的生存期

    创一个小群,供大家学习交流聊天

    如果有对学C++方面有什么疑惑问题的,或者有什么想说的想聊的大家可以一起交流学习一起进步呀。

    也希望大家对学C++能够持之以恒

    C++爱好群,

    如果你想要学好C++最好加入一个组织,这样大家学习的话就比较方便,还能够共同交流和分享资料,给你推荐一个学习的组织:快乐学习C++组织 可以点击组织二字,可以直达

    构造函数和析构函数都是类的成员函数,但它们都是特殊的成员函数,执行特殊的功能,不用调用便自动执行,而且这些函数的名字与类的名字有关。

    C++语言中有一些成员函数性质是特殊的,这些成员函数负责对象的建立、删除。这些函数的特殊性在于可以由编译器自动地隐含调用,其中一些函数调用格式采用运算符函数重载的语法。

    C++引进一个自动完成对象初始化过程的机制,这就是类的构造函数。

    对象的初始化

    1、数据成员是不能在声明类时初始化

    2、类型对象的初始化方法:

    1) 调用对外接口(public成员函数)实现:声明类→定义对象→调用接口给成员赋值

    2) 应用构造函数(constructor) 实现:声明类→定义对象→同时给成员赋值

    1、构造函数

    构造函数是一种特殊的成员函数,它主要用于为对象分配空间,进行初始化。

    1.1 构造函数具有一些特殊的性质:

    (1) 构造函数的名字必须与类名相同。

    (2) 构造函数可以有任意类型的参数,但不能指定返回类型。 它有隐含的返回值,该值由系统内部使用。

    (3) 构造函数是特殊的成员函数,函数体可写在类体内,也可写在类体外。

    (4) 构造函数可以重载,即一个类中可以定义多个参数个数或参数类型不同的构造函数。构造函数是不能继承

    (5) 构造函数被声明为公有函数,但它不能像其他成员函数那样被显式地调用,它是在定义对象的同时被调用的。

    (6) 在声明类时如果没有定义类的构造函数,编译系统就会在编译时自动生成一个默认形式的构造函数,

    (7) 默认构造函数是构造对象时不提供参数的构造函数。

    (8) 除了无参数构造函数是默认构造函数外,带有全部默认参数值的构造函数也是默认构造函数。

    (9) 自动调用:构造函数在定义类对象时自动调用, 不需用户调用,也不能被用户调用。在对象使用前调用。

    (10) 调用顺序:在对象进入其作用域时(对象使用前) 调用构造函数。

    1.2 定义构造函数的一般形式

    class类名

    {

    public:

    类名(形参表) ;//构造函数的原型

    //类的其它成员

    };

    类名::类名(形参表)//构造函数的实现

    {

    //函数体

    }

    1.3 利用构造函数创建对象

    (1) 利用构造函数直接创建对象.其一般形式为:类名 对象名[(实参表)];

    这里的“类名”与构造函数名相同,“实参表”是为构造函数提供的实际参数。

    例2.7 为类Date建立一个构造函数

    #include<iostream.h>

    classDate{

    public:

    Date(inty,intm,intd);// 构造函数

    voidsetDate(inty,intm,intd);

    voidshowDate();

    private:

    intyear, month, day;

    };

    Date::Date(inty,intm,intd)// 构造函数的实现

    { year=y; month=m; day=d; }

    voidDate::setDate(inty,intm,intd)

    { year=y; month=m; day=d; }

    inlinevoidDate::showDate()

    {cout<

    例2.8 利用构造函数直接创建对象

    #include<iostream.h>

    classDate{

    // 省略, 同例2.7

    };

    // 省略, 同例2.7

    voidmain()

    {

    Datedate1(1998,4,28);// 定义类Date的对象date1,

    // 自动调用date1的构造函数,初始化对象date1

    cout<<"Date1 output1:"<

    date1.showDate();// 调用date1的showDate(),显示date1的数据

    date1.SetDate(2002,11,14);// 调用date1的setDate(),

    // 重新设置date1的数据

    cout<<"Date1 output2:"<

    date1.showDate();// 调用date1的showDate(),显示date1的数据

    }

    constructing...

    Date1output1:

    1998.4.28

    Date1output2:

    2002.11.14

    (2) 利用构造函数创建对象时,通过指针和new来实现。其一般语法形式为:

    类名 *指针变量 = new 类名[(实参表)];

    voidmain()

    {

    Date *date1;

    date1=newDate(1998,4,28);

    //可合写成:Date *date1=new Date(1998,4,28);

    cout<<"Date1 output1:"<

    date1->showDate();

    date1->setDate(2002,11,14);

    cout<<"Date1 output2:"<

    date1->showDate();

    deletedate1;

    }

    说明:

    构造函数的名字必须与类名相同,否则编译器将把它当作一般的成员函数来处理。

    构造函数是不能说明它的返回值类型的,甚至说明为void类型也不行。

    构造函数可以是不带参数的。

    classA{

    public:

    A();

    //…

    private:

    intx;

    };

    A∷A()

    {

    cout<<"initialized \n";

    x=50;

    }

    main()

    {

    A a;

    }

    有两个长方柱,其长、宽、高分别为:(1)12,25,30;(2)15,30,21。求它们的体积。要求:编一个基于对象的程序,在类中用带参数的构造函数。

    classBox{

    public:

    Box(int,int,int);

    intvolume( );

    private:

    intheight;

    intwidth;

    intlength;

    };

    Box::Box(inth,intw,intlen)

    {

    height = h;

    width = w;

    length = len;

    }

    intBox::volume( )

    {

    returnheight*width*length;

    }

    intmain( )

    {

    Boxbox1(12,25,30);

    cout<< box1.volume( ) <

    Boxbox2(15,30,21);

    cout<< box2.volume( ) <

    return0;

    }

    2、成员初始化表

    对于常量类型和引用类型的数据成员,不能在构造函数中用赋值语句直接赋值,C++提供初始化表进行置初值。

    带有成员初始化表的构造函数的一般形式如下:

    类名::构造函数名([参数表])[:(成员初始化表)]

    {

    // 构造函数体

    }

    成员初始化表的一般形式为:

    数据成员名1(初始值1),数据成员名2(初始值2),……

    例2.9 成员初始化表的使用

    #include<iostream.h>

    classA{

    public:

    A(intx1):x(x1),rx(x),pi(3.14)// rx(x)相当于rx=x, pi(3.14)相当于pi=3.14

    { }

    voidprint()

    {cout<<"x="<

    private:

    intx;int& rx;constfloatpi;

    };

    main()

    {

    Aa(10);

    a.print();

    return0;

    }

    构造函数采用成员初始化表对数据成员进行初始化,是一些程序员喜欢使用的方法。

    classB{

    inti;

    charj;

    floatf;

    public:

    B(intI,charJ,floatF)

    { i=I; j=J; f=F; };

    };

    classB{

    public:

    B(intI,charJ,floatF):i(I),j(J),f(F)

    { }

    private:

    inti;

    charj;

    floatf;

    };

    说明

    如果需要将数据成员存放在堆中或数组中,则应在构造函数中使用赋值语句,即使构造函数有成员初始化表也应如此。

    classC{

    public:

    C(int I,char Ch,float F,char N[]):i(I),ch(Ch),f(F)

    { strcpy (name,N);}

    private:

    inti;

    charch;

    floatf;

    charname[25];

    };

    类成员是按照它们在类里被声明的顺序初始化的,与它们在初始化表中列出的顺序无关。

    【例2.10】

    #include<iostream.h>

    classD{

    public:

    D(inti):mem2(i),mem1(mem2+1)

    {

    cout<<"mem1: "<

    cout<<"mem2: "<

    }

    private:

    intmem1;

    intmem2;

    };

    voidmain()

    {

    Dd(15);

    }

    mem1: -858993459

    mem2: 15

    3、缺省参数的构造函数

    例2.11

    #include<iostream.h>

    classCoord{

    public:

    Coord(inta=0,intb=0){ x=a; y=b;}// 带有缺省参数的构造函数

    intgetx(){returnx; }

    intgety(){returny; }

    private:

    intx,y;

    };

    voidmain()

    {

    Coordop1(5,6);Coordop2(5); Coord op3;

    inti,j;

    i=op1.getx();j=op1.gety();

    cout<<"op1 i= "<

    i=op2.getx();j=op2.gety();

    cout<<"op2 i= "<

    i=op3.getx();j=op3.gety();

    cout<<"op3 i= "<

    }

    classBox{

    public:

    Box(inth=10,intw=10,intl=10);//在声明构造函数时指定默认参数

    intvolume( ){return(height*width*length); }

    private:

    intheight;

    intwidth;

    intlength;

    };

    Box:: Box(inth,intw,intl)//在定义函数时可以不指定默认参数

    {

    height=h;

    width=w;

    length=l;

    }

    4、重载构造函数

    构造函数的重载

    在一个类中可以定义多个构造函数,以便对类对象提供不同的初始化的方法,供用户选用。这些构造函数具有相同的名字,而参数的个数或参数的类

    型不相同(这称为构造函数的重载)

    关于构造函数重载的说明

    (1) 默认构造函数:一个调用构造函数时不必给出实参的构造函数。 显然,无参的构造函数属于默认构造函数。一个类只能有一个默认构造函数。

    (2) 尽管在一个类中可以包含多个构造函数,但是对于每一个对象来说,建立对象时只执行其中一个构造函数,并非每个构造函数都被执行。

    classBox{

    public:

    Box(inth,intw,intl): height(h),width(w),length(l) { }

    Box();

    intvolume( );

    private:

    intheight;

    intwidth;

    intlength;

    };

    Box::Box()

    {

    height =10;

    width =10;

    lenght =10;

    }

    intBox::volume( )

    {

    returnheight*width*length;

    }

    intmain( )

    {

    Box box1;// 书上为 box1();

    cout<< box1.volume( ) <

    Boxbox2(15,30,25);

    cout<< box2.volume( ) <

    return0;

    }

    例2.17 重载构造函数应用例程。

    #include<iostream.h>

    classDate{

    public:

    Date();// 无参数的构造函数

    Date(inty,intm,intd);// 带有参数的构造函数

    voidshowDate();

    private:

    intyear, month, day;

    };

    Date::Date()

    { year=1998; month=4; day=28; }

    Date::Date(inty,intm,intd)

    { year=y; month=m; day=d; }

    inlinevoidDate::showDate()

    {cout<

    voidmain()

    {

    Date date1;// 声明类Date的对象date1,

    // 调用无参数的构造函数

    cout<<"Date1 output: "<

    date1.showDate();// 调用date1的showDate(),显示date1的数据

    Datedate2(2002,11,14);// 定义类Date的对象date2,

    // 调用带参数的构造函数

    cout<<"Date2 output: "<

    date2.showDate();// 调用date2的showDate(),显示date2的数据

    }

    运行结果:

    Date1output:

    1998.4.28

    Date2output:

    2002.11.14

    例2.18 关于计时器的例子

    #include<iostream.h>

    #include<stdlib.h>

    classtimer{

    public:

    timer()// 无参数构造函数,给seconds清0

    { seconds=0; }

    timer(char* t)// 含一个数字串参数的构造函数

    { seconds=atoi(t); }

    timer(intt)// 含一个整型参数的构造函数

    { seconds=t; }

    timer(intmin,intsec)// 含两个整型参数的构造函数

    { seconds=min*60+sec; }

    intgettime()

    {returnseconds; }

    private:

    intseconds;

    };

    main()

    {

    timer a,b(10),c("20"),d(1,10);

    cout<<"seconds1="<

    cout<<"seconds2="<

    cout<<"seconds3="<

    cout<<"seconds4="<

    return0;

    }

    classx{

    public:

    x();// 没有参数的构造函数

    x(inti=0);// 带缺省参数的构造函数

    };

    //…

    voidmain()

    {

    xone(10);// 正确,调用x(int i=0)

    x two;// 存在二义性

    //…

    }

    5、拷贝构造函数

    拷贝构造函数是一种特殊的构造函数,其形参是本类对象的引用。其作用是使用一个已经存在的对象去初始化另一个同类的对象。

    通过等于号复制对象时,系统会自动调用拷贝构造函数。

    拷贝构造函数与原来的构造函数实现了函数的重载。

    拷贝构造函数具有以下特点:

    (1) 因为该函数也是一种构造函数,所以其函数名与类名相同,并且该函数也没有返回值类型。

    (2) 该函数只有一个参数,并且是同类对象的引用。

    (3) 每个类都必须有一个拷贝构造函数。程序员可以根据需要定义特定的拷贝构造函数,以实现同类对象之间数据成员的传递。如果程序员没有定义类的拷贝构造函数,系统就会自动生成产生一个缺省的拷贝构造函数。

    5.1 自定义拷贝构造函数

    自定义拷贝构造函数的一般形式如下:

    class类名{

    public:

    类名(形参);//构造函数

    类名(类名 &对象名);//拷贝构造函数

    ...

    };

    类名:: 类名(类名 &对象名)//拷贝构造函数的实现

    { 函数体 }

    用户自定义拷贝构造函数

    classCoord{

    intx,y;

    public:

    Coord(inta,intb)// 构造函数

    {

    x=a;

    y=b;

    cout<<"Using normal constructor\n";

    }

    Coord(constCoord& p)// 拷贝构造函数

    {

    x=2*p.x;

    y=2*p.y;

    cout<<"Using copy constructor\n";

    }

    //…

    };

    如果p1、 p2为类Coord的两个对象,p1已经存在,则coord p2(p1)调用拷贝构造函数来初始化p2

    例2.19 自定义拷贝构造函数的使用

    #include<iostream.h>

    classCoord{

    public:

    Coord(inta,intb)// 构造函数

    { x=a; y=b;cout<<"Using normal constructor\n";}

    Coord(constCoord& p)// 拷贝构造函数

    { x=2*p.x; y=2*p.y;cout<<"Using copy constructor\n";}

    voidprint(){cout<

    private:

    intx,y;

    };

    main()

    {

    Coordp1(30,40);// 定义对象p1,调用了普通的构造函数

    Coordp2(p1);// 以“代入” 法调用拷贝构造函数,用对象p1初始化对象p2

    p1.print();

    p2.print();

    return0;

    }

    除了用代入法调用拷贝构造函数外,还可以采用赋值法调用拷贝构造函数,如:

    main()

    {

    Coordp1(30,40);

    Coord p2=p1;//以"赋值"法调用拷贝构造函数,

    用对象p1初始化对象p2

    //…

    }

    5.2 缺省的拷贝构造函数

    如果没有编写自定义的拷贝构造函数,C++会自动地将一个已存在的对象复制给新对象,这种按成员逐一复制的过程由是缺省拷贝构造函数自动完成的。

    例2.20 调用缺省的拷贝构造函数

    #include<iostream.h>

    classCoord{

    public:

    Coord(inta,intb)

    { x=a; y=b;cout<<"Using normal constructor\n"; }

    voidprint(){cout<

    private:

    intx,y;

    };

    main()

    {

    Coordp1(30,40);// 定义类Coord的对象p1,

    // 调用了普通构造函数初始化对象p1

    Coordp2(p1);// 以“代入”法调用缺省的拷贝构造函数,

    // 用对象p1初始化对象p2

    Coord p3=p1;// 以“赋值”法调用缺省的拷贝构造函数,

    // 用对象p1初始化对象p3

    p1.print(); p2.print(); p3.print();

    return0;

    }

    5.3 调用拷贝构造函数的三种情况

    (1) 当用类的一个对象去初始化该类的另一个对象时。

    Coordp2(p1);// 用对象p1初始化对象p2, 拷贝构造函数被调用(代入法)

    Coord p3=p1;// 用对象p1初始化对象p3, 拷贝构造函数被调用(赋值法)

    (2) 当函数的形参是类的对象,调用函数,进行形参和实参结合时。

    //…

    fun1(Coord p)// 函数的形参是类的对象

    {

    p.print();

    }

    main()

    {

    Coordp1(10,20);

    fun1(p1);// 当调用函数,进行形参和实参结合时,

    调用拷贝构造函数

    return0;

    }

    (3) 当函数的返回值是对象,函数执行完成,返回调用者时。

    // …

    Coordfun2()

    {

    Coordp1(10,30);

    returnp1;

    }// 函数的返回值是对象

    main()

    {

    Coord p2;

    P2=fun2();// 函数执行完成,返回调用者时,调用拷贝构造函数

    return0;

    }

    5.4 浅拷贝和深拷贝

    所谓浅拷贝,就是由缺省的拷贝构造函数所实现的数据成员逐一赋值,若类中含有指针类型数据, 则会产生错误。

    为了解决浅拷贝出现的错误,必须显示地定义一个自己的拷贝构造函数,使之不但拷贝数据成员,而且为对象1和对象2分配各自的内存空间,这就是所谓的深拷贝。

    例2.23 浅拷贝例子

    #include<iostream.h>

    #include<string.h>

    classStudent{

    public:

    Student(char*name1,floatscore1);

    ~Student();

    private:

    char*name;// 学生姓名

    floatscore;// 学生成绩

    };

    Student∷Student(char*name1,floatscore1)

    {

    cout<<"Constructing..."<

    name=newchar[strlen(name1)+1];

    if(name !=0)

    {

    strcpy(name,name1);

    score=score1;

    }

    }

    Student∷~Student()

    {

    cout<<"Destructing..."<

    name[0]='\0';

    deletename;

    }

    voidmain()

    {

    Studentstu1("liming",90);// 定义类Student的对象stu1

    Student stu2=stu1;// 调用缺省的拷贝构造函数

    }

    Constructing... liming

    Destructing... liming

    Destructing...

    浅拷贝示意图

    例2.24 深拷贝例子

    #include<iostream.h>

    #include<string.h>

    classStudent{

    private:

    char*name;// 学生姓名

    floatscore;// 学生成绩

    public:

    Student(char*name1,floatscore1);

    Student(Student& stu);

    ~Student();

    };

    Student∷Student(char*name1,floatscore1)

    {

    cout<<"constructing..."<

    name=newchar[strlen(name1)+1];

    if(name !=0)

    {

    strcpy(name,name1);

    score=score1;

    }

    }

    Student∷Student(Student& stu)

    {

    cout<<"Copy constructing..."<

    name=newchar[strlen(stu.name)+1];

    if(name !=0)

    {

    strcpy(name,stu.name);

    score=stu.score;

    }

    }

    Student∷~Student()

    {

    cout<<"Destructing..."<

    name[0]='\0';

    deletename;

    }

    voidmain()

    {

    Studentstu1("liming",90);// 定义类Student的对象stu1,

    Student stu2=stu1;// 调用自定义的拷贝构造函数

    }

    深拷贝示意图

    6、析构函数

    析构函数也是一种特殊的成员函数。它执行与构造函数相反的操作,通常用于撤消对象时的一些清理任务,如释放分配给对象的内存空间等。

    析构函数有以下一些特点:

    ① 析构函数与构造函数名字相同,但它前面必须加一个波浪号(~);

    ② 析构函数没有参数,也没有返回值,而且不能重载。因此在一个类中只能有一个析构函数;

    ③ 当撤消对象时,编译系统会自动地调用析构函数。 如果程序员没有定义析构函数,系统将自动生成和调用一个默认析构函数,默认析构函数只能释放对象的数据成员所占用的空间,但不包括堆内存空间。

    例2.25 重新说明类Date

    #include<iostream.h>

    classDate{

    public:

    Date(inty,intm,intd);// 构造函数

    ~Date();// 析构函数

    voidsetDate(inty,intm,intd);

    voidshowDate();

    private:

    intyear, month, day;

    };

    Date::Date(inty,intm,intd)// 构造函数的实现

    {

    cout<<"constructing..."<

    year=y;month=m; day=d;

    }

    Date::~Date()// 析构函数的实现

    {cout<<"destruting..."<

    voidDate::setDate(inty,intm,intd)

    { year=y;month=m;day=d; }

    inlinevoidDate::showDate()

    {cout<

    voidmain()

    {

    Datedate1(1998,4,28);// 定义类Date的对象date1,

    // 调用date1的构造函数,初始化对象date1

    cout<<"Date1 output1:"<

    date1.showDate();// 调用date1的showDate(),显示date1的数据

    date1.setDate(2002,11,14);// 调用date1的setDate(),

    // 重新设置date1的数据

    cout<<"Date1 output2:"<

    date1.showDate();// 调用date1的showDate(),显示date1的数据

    }

    析构函数被调用的两种情况

    1) 若一个对象被定义在一个函数体内,当这个函数结束时,析构函数被自动调用。

    2) 若一个对象是使用new运算符动态创建,在使用delete释放时,自动调用析构函数。

    【例2.13】 较完整的学生类例子

    #include<iostream.h>

    #include<string.h>

    classStudent{

    public:

    Student(char*name1,char*stu_no1,floatscore1);// 构造

    函数

    ~Student();// 析构函数

    voidmodify(floatscore1);// 修改数据

    voidshow();// 显示数据

    private:

    char*name;// 学生姓名

    char*stu_no;// 学生学号

    floatscore;// 学生成绩

    };

    Student∷Student(char*name1,char*stu_no1,floatscore1)

    {

    name=newchar[strlen(name1)+1];

    strcpy(name,name1);

    stu_no=newchar[strlen(stu_no1)+1];

    strcpy(stu_no,stu_no1);

    score=score1;

    }

    Student∷~Student()

    {

    delete[]name;

    delete[]stu_no;

    }

    voidStudent∷modify(floatscore1)

    { score=score1; }

    voidStudent∷show()

    {

    cout<<"\n name: "<

    cout<<"\n stu_no: "<

    cout<<"\n score: "<

    }

    voidmain()

    {

    Studentstu1("Liming","990201",90);// 定义类Student的对象stu1,

    // 调用stu1的构造函数,初始化对象stu1

    stu1.show();// 调用stu1的show(),显示stu1的数据

    stu1.modify(88);// 调用stu1的modify(),修改stu1的数据

    stu1.show();// 调用stu1的show(),显示stu1修改后的数据

    }

    ame:Liming

    stu_no:990201

    score:90

    name:Liming

    stu_no:990201

    score:88

    缺省的析构函数

    每个类必须有一个析构函数。

    若没有显式地为一个类定义析构函数,编译系统会自动地生成一个缺省的析构函数

    其格式如下:类名::析构函数名( ){ }

    classstring_data{

    public:

    string_data(char*)

    { str=newchar[max_len];}

    ~string_data()

    {delete[]str;}

    voidget_info(char*);

    voidsent_info(char*);

    private:

    char*str;

    intmax_len;

    };

    7、调用构造函数和析构函数的顺序

    1) 一般顺序

    调用析构函数的次序正好与调用构造函数的次序相反:最先被调用的构造函数,其对应的(同一对象中的)析构函数最后被调用,而最后被调用的构造函数,其对应的析构函数最先被调用。

    2) 全局对象

    在全局范围中定义的对象(即在所有函数之外定义的对象),它的构造函数在所有函数(包括main函数)执行之前调用。在程序的流程离开其作用域时(如main函数结束或调用exit函数)时,调用该全局对象的析构函数。

    3) auto局部对象

    局部自动对象(例如在函数中定义的对象),则在建立对象时调用其构造函数。如果函数被多次调用,则在每次建立对象时都要调用构造函数。在函数调用结束、对象释放时先调用析构函数。

    4) static局部对象

    如果在函数中定义静态局部对象,则只在程序第一次调用此函数建立对象时调用构造函数一次,在调用结束时对象并不释放,因此也不调用析构函数,只在main函数结束或调用exit函数结束程序时,才调用析构函数。

    8. 对象的生存期

    对象按生存期的不同分为如下几种:

    (1) 局部对象

    当对象被定义时,调用构造函数,该对象被创建;当程序退出该对象所在的函数体或程序块时,调用析构函数,对象被释放。

    局部对象是被定义在一个函数体或程序块内的,它的作用域限定在函数体或程序块内,生存期较短。

    (2) 全局对象

    当程序开始运行时,调用构造函数,该对象被创建;当程序结束时,调用析构函数,该对象被释放。

    静态对象是被定义在一个文件中,它的作用域从定义是起到文件结束时为止。生存期较长。

    (3) 静态对象

    当程序中定义静态对象时,调用构造函数,该对象被创建;当整个程序结束时,调用析构函数,对象被释放。

    全局对象是被定义在某个文件中,它的作用域包含在该文件的整个程序中,生存期是最长的。

    (4) 动态对象

    执行new运算符调用构造函数,动态对象被创建;用delete释放对象时,调用析构函数。

    动态对象是由程序员掌握的,它的作用域和生存期是由new和delete之间的间隔决定的。

    类的应用举例(例)

    一圆形游泳池如图所示,现在需在其周围建一圆形过道,并在其四周围上栅栏。栅栏价格为35元/米,过道造价为20元/平方米。过道宽度为3米,游泳池半径由键盘输入。要求编程计算并输出过道和栅栏的造价。

    #include<iostream>

    usingnamespacestd;

    constfloatPI =3.14159;

    constfloatFencePrice =35;

    constfloatConcretePrice =20;

    //声明类Circle 及其数据和方法

    classCircle{

    private:

    floatradius;

    public:

    Circle(floatr);//构造函数

    floatCircumference()const;//圆周长

    /*函数后的修饰符const表示该成员函数的执行不会改变类的状态,也就是说不会修改类的数据成员。 */

    floatArea()const;//圆面积

    };// 类的实现

    // 构造函数初始化数据成员radius

    Circle::Circle(floatr)

    {

    radius=r;

    }

    // 计算圆的周长

    floatCircle::Circumference()const

    {

    return2* PI * radius;

    }

    // 计算圆的面积

    floatCircle::Area()const

    {

    returnPI * radius * radius;

    }

    voidmain()

    {

    floatradius;

    floatFenceCost, ConcreteCost;

    // 提示用户输入半径

    cout<<"Enter the radius of the pool: ";

    cin>>radius;

    // 声明 Circle 对象

    CirclePool(radius);

    CirclePoolRim(radius +3);

    //计算栅栏造价并输出

    FenceCost=PoolRim.Circumference()*FencePrice;

    cout<<"Fencing Cost is ¥"<

    //计算过道造价并输出

    ConcreteCost=(PoolRim.Area()-

    Pool.Area())*ConcretePrice;

    cout<<"Concrete Cost is ¥"<

    }

    运行结果

    Enter the radiusofthe pool:10

    Fencing Costis¥2858.85

    Concrete Costis¥4335.39

    相关文章

      网友评论

          本文标题:C++ 构造函数与析构函数

          本文链接:https://www.haomeiwen.com/subject/lznamqtx.html