zoukankan      html  css  js  c++  java
  • C++_构造函数与析构函数

    构造函数与析构函数

    • 1 构造函数
      • 1.1 构造函数具有一些特殊的性质
      • 1.2 定义构造函数的一般形式
      • 1.3 利用构造函数创建对象
    • 2 成员初始化表
    • 3 缺省参数的构造函数
    • 4 重载构造函数
    • 5 拷贝构造函数
      • 5.1 自定义拷贝构造函数
      • 5.2 缺省的拷贝构造函数
      • 5.3 调用拷贝构造函数的三种情况
      • 5.4 浅拷贝和深拷贝
    • 6 析构函数
    • 7 调用构造函数和析构函数的顺序
    • 8 对象的生存期

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

    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>
    class Date {
    public:
        Date(int y,int m,int d); // 构造函数
        void setDate(int y,int m,int d);
        void showDate();
    private:
        int year, month, day;
    };
    Date::Date(int y,int m,int d) // 构造函数的实现
    { year=y; month=m; day=d; }
    void Date::setDate(int y,int m,int d)
    { year=y; month=m; day=d; }
    inline void Date::showDate()
    { cout<<year<<"."<<month<<"."<<day<<endl; }
    
    例2.8 利用构造函数直接创建对象
    #include <iostream.h>
    class Date {
    // 省略, 同例2.7
    };
    // 省略, 同例2.7
    void main()
    {
        Date date1(1998,4,28); // 定义类Date的对象date1,
        // 自动调用date1的构造函数,初始化对象date1
        cout<<"Date1 output1:"<<endl;
        date1.showDate(); // 调用date1的showDate(),显示date1的数据
        date1.SetDate(2002,11,14); // 调用date1的setDate(),
        // 重新设置date1的数据
        cout<<"Date1 output2:"<<endl;
        date1.showDate(); // 调用date1的showDate(),显示date1的数据
    }
    
    constructing...
    Date1 output1:
    1998.4.28
    Date1 output2:
    2002.11.14
    
    • (2) 利用构造函数创建对象时,通过指针和new来实现。其一般语法形式为:
      类名 *指针变量 = new 类名 (实参表);
    void main()
    {
        Date *date1;
        date1=new Date(1998,4,28);
        //可合写成:Date *date1=new Date(1998,4,28);
        cout<<"Date1 output1:"<<endl;
        date1->showDate();
        date1->setDate(2002,11,14);
        cout<<"Date1 output2:"<<endl;
        date1->showDate();
        delete date1;
    }
    

    说明:

    • 构造函数的名字必须与类名相同,否则编译器将把它当作一般的成员函数来处理。
    • 构造函数是不能说明它的返回值类型的,甚至说明为void类型也不行。
    • 构造函数可以是不带参数的。
    class A{
    public:
        A();
        //…
    private:
        int x;
    };
    A∷A()
    {
        cout<<"initialized 
    ";
        x=50;
    }
    main()
    {
        A a;
        …
    }
    

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

    class Box{
    public:
        Box(int,int,int);
        int volume( );
    private:
        int height;
        int width;
        int length;
    };
    Box::Box(int h,int w,int len)
    {
        height = h;
        width = w;
        length = len;
    }
    int Box::volume( )
    {
        return height*width*length;
    }
    int main( )
    {
        Box box1(12,25,30);
        cout << box1.volume( ) << endl;
        Box box2(15,30,21);
        cout << box2.volume( ) << endl;
        return 0;
    }
    

    2. 成员初始化表

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

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

    类名::构造函数名(参数表): (成员初始化表){ 构造函数体 }

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

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

    例2.9 成员初始化表的使用
    #include<iostream.h>
    class A{
    public:
        A(int x1):x(x1),rx(x),pi(3.14) // rx(x)相当于rx=x, pi(3.14)相当于pi=3.14
        { }
        void print()
        {cout<<"x="<<x<<" "<<"rx="<<rx<<" "<<"pi="<<pi;}
    private:
        int x; int& rx; const float pi;
    };
    main()
    {
        A a(10);
        a.print();
        return 0;
    }
    
    • 构造函数采用成员初始化表对数据成员进行初始化,是一些程序员喜欢使用的方法。
    class B{
        int i;
        char j;
        float f;
    public:
        B(int I, char J, float F)
        { i=I; j=J; f=F; };
    };
    
    class B{
    public:
        B(int I,char J,float F):i(I),j(J),f(F)
        { }
    private:
        int i;
        char j;
        float f;
    };
    

    说明

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

    class C{
    public:
        C(int I,char Ch,float F,char N[]):i(I),ch(Ch),f(F)
        { strcpy (name,N);}
    private:
        int i;
        char ch;
        float f;
        char name[25];
    };
    
    • 类成员是按照它们在类里被声明的顺序初始化的,与它们在初始化表中列出的顺序无关。
    【例2.10】
    #include<iostream.h>
    class D {
    public:
        D(int i):mem2(i),mem1(mem2+1)
        {
            cout<<"mem1: "<<mem1<<endl;
            cout<<"mem2: "<<mem2<<endl;
        }
    private:
        int mem1;
        int mem2;
    };
    void main()
    {
        D d(15);
    }
    
    mem1: -858993459
    mem2: 15
    

    3. 缺省参数的构造函数

    例2.11
    #include<iostream.h>
    class Coord {
    public:
        Coord(int a=0,int b=0){ x=a; y=b;} // 带有缺省参数的构造函数
        int getx(){ return x; }
        int gety(){ return y; }
    private:
        int x,y;
    };
    void main()
    {
        Coord op1(5,6); Coord op2(5); Coord op3;
        int i,j;
        i=op1.getx();j=op1.gety();
        cout<<"op1 i= "<<i<<" op1 j= "<<j<<endl;
        i=op2.getx();j=op2.gety();
        cout<<"op2 i= "<<i<<" op2 j= "<<j<<endl;
        i=op3.getx();j=op3.gety();
        cout<<"op3 i= "<<i<<" op3 j= "<<j<<endl;
    }
    
    class Box{
    public:
        Box(int h=10,int w=10,int l=10); //在声明构造函数时指定默认参数
        int volume( ){ return(height*width*length); }
    private:
        int height;
        int width;
        int length;
    };
    Box:: Box(int h,int w,int l) //在定义函数时可以不指定默认参数
    {
        height=h;
        width=w;
        length=l;
    }
    

    4. 重载构造函数

    构造函数的重载

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

    关于构造函数重载的说明

    • (1) 默认构造函数:一个调用构造函数时不必给出实参的构造函数。 显然,无参的构造函数属于默认构造函数。一个类只能有一个默认构造函数。
    • (2) 尽管在一个类中可以包含多个构造函数,但是对于每一个对象来说,建立对象时只执行其中一个构造函数,并非每个构造函数都被执行。
    class Box{
    public:
        Box(int h, int w, int l): height(h),width(w),length(l) { }
        Box();
        int volume( );
    private:
        int height;
        int width;
        int length;
    };
    Box::Box()
    {
        height = 10;
        width = 10;
        lenght = 10;
    }
    int Box::volume( )
    {
        return height*width*length;
    }
    int main( )
    {
        Box box1; // 书上为 box1();
        cout << box1.volume( ) << endl;
        Box box2(15,30,25);
        cout << box2.volume( ) << endl;
        return 0;
    }
    
    例2.17 重载构造函数应用例程。
    #include <iostream.h>
    class Date{
    public:
        Date(); // 无参数的构造函数
        Date(int y,int m,int d); // 带有参数的构造函数
        void showDate();
    private:
        int year, month, day;
    };
    Date::Date()
    { year=1998; month=4; day=28; }
    Date::Date( int y, int m, int d)
    { year=y; month=m; day=d; }
    inline void Date::showDate()
    { cout<<year<<"."<<month<<"."<<day<<endl; }
    void main()
    {
        Date date1; // 声明类Date的对象date1,
        // 调用无参数的构造函数
        cout<<"Date1 output: "<<endl;
        date1.showDate(); // 调用date1的showDate(),显示date1的数据
        Date date2(2002, 11, 14); // 定义类Date的对象date2,
        // 调用带参数的构造函数
        cout<<"Date2 output: "<<endl;
        date2.showDate(); // 调用date2的showDate(),显示date2的数据
    }
    

    运行结果:

    Date1 output:
    1998.4.28
    Date2 output:
    2002.11.14
    
    例2.18 关于计时器的例子
    #include<iostream.h>
    #include<stdlib.h>
    class timer{
    public:
        timer() // 无参数构造函数,给seconds清0
        { seconds=0; }
        timer(char* t) // 含一个数字串参数的构造函数
        { seconds=atoi(t); }
        timer(int t) // 含一个整型参数的构造函数
        { seconds=t; }
        timer(int min,int sec) // 含两个整型参数的构造函数
        { seconds=min*60+sec; }
        int gettime()
        { return seconds; }
    private:
        int seconds;
    };
    main()
    {
        timer a,b(10),c("20"),d(1,10);
        cout<<"seconds1="<<a.gettime()<<endl;
        cout<<"seconds2="<<b.gettime()<<endl;
        cout<<"seconds3="<<c.gettime()<<endl;
        cout<<"seconds4="<<d.gettime()<<endl;
        return 0;
    }
    
    class x {
    public:
        x(); // 没有参数的构造函数
        x(int i=0); // 带缺省参数的构造函数
    };
    //…
    void main()
    {
        x one(10); // 正确,调用x(int i=0)
        x two; // 存在二义性
        //…
    }
    

    5. 拷贝构造函数

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

    • 通过等于号复制对象时,系统会自动调用拷贝构造函数。
    • 拷贝构造函数与原来的构造函数实现了函数的重载。

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

    • (1) 因为该函数也是一种构造函数,所以其函数名与类名相同,并且该函数也没有返回值类型。
    • (2) 该函数只有一个参数,并且是同类对象的引用
    • (3) 每个类都必须有一个拷贝构造函数。程序员可以根据需要定义特定的拷贝构造函数,以实现同类对象之间数据成员的传递。如果程序员没有定义类的拷贝构造函数,系统就会自动生成产生一个缺省的拷贝构造函数。

    5.1 自定义拷贝构造函数

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

    class 类名{
    public :
        类名(形参); //构造函数
        类名(类名 &对象名); //拷贝构造函数
    ...
    };
    类名:: 类名(类名 &对象名) //拷贝构造函数的实现
    { 函数体 }
    
    用户自定义拷贝构造函数
    class Coord{
        int x,y;
    public:
        Coord(int a, int b) // 构造函数
        {
            x=a;
            y=b;
            cout<<"Using normal constructor
    ";
        }
        Coord(const Coord& p) // 拷贝构造函数
        {
            x=2*p.x;
            y=2*p.y;
            cout<<"Using copy constructor
    ";
        }
        //…
    };
    

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

    例2.19 自定义拷贝构造函数的使用
    #include<iostream.h>
    class Coord {
    public:
        Coord(int a,int b) // 构造函数
        { x=a; y=b; cout<<"Using normal constructor
    ";}
        Coord(const Coord& p) // 拷贝构造函数
        { x=2*p.x; y=2*p.y; cout<<"Using copy constructor
    ";}
        void print(){ cout<<x<<" "<<y<<endl; }
    private:
        int x,y;
    };
    main()
    {
        Coord p1(30,40); // 定义对象p1,调用了普通的构造函数
        Coord p2(p1); // 以“代入” 法调用拷贝构造函数,用对象p1初始化对象p2
        p1.print();
        p2.print();
        return 0;
    }
    

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

    main()
    {
        Coord p1(30,40);
        Coord p2=p1; //以"赋值"法调用拷贝构造函数,
        用对象p1初始化对象p2
        //…
    }
    

    5.2 缺省的拷贝构造函数

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

    例2.20 调用缺省的拷贝构造函数
    #include<iostream.h>
    class Coord{
    public:
        Coord(int a,int b)
        { x=a; y=b; cout<<"Using normal constructor
    "; }
        void print(){ cout<<x<<" "<<y<<endl;}
    private:
        int x,y;
    };
    main()
    {
        Coord p1(30,40); // 定义类Coord的对象p1,
        // 调用了普通构造函数初始化对象p1
        Coord p2(p1); // 以“代入”法调用缺省的拷贝构造函数,
        // 用对象p1初始化对象p2
        Coord p3=p1; // 以“赋值”法调用缺省的拷贝构造函数,
        // 用对象p1初始化对象p3
        p1.print(); p2.print(); p3.print();
        return 0;
    }
    

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

    • (1) 当用类的一个对象去初始化该类的另一个对象时。
    Coord p2(p1); // 用对象p1初始化对象p2, 拷贝构造函数被调用(代入法)
    Coord p3=p1; // 用对象p1初始化对象p3, 拷贝构造函数被调用(赋值法)
    
    • (2) 当函数的形参是类的对象,调用函数,进行形参和实参结合时。
    //…
    fun1(Coord p) // 函数的形参是类的对象
    {
        p.print();
    }
    main()
    {
        Coord p1(10,20);
        fun1(p1); // 当调用函数,进行形参和实参结合时,
        调用拷贝构造函数
        return 0;
    }
    
    • (3) 当函数的返回值是对象,函数执行完成,返回调用者时。
    // …
    Coord fun2()
    {
        Coord p1(10,30);
        return p1;
    } // 函数的返回值是对象
    main()
    {
        Coord p2;
        P2=fun2(); // 函数执行完成,返回调用者时,调用拷贝构造函数
        return 0;
    }
    

    5.4 浅拷贝和深拷贝

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

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

    例2.23 浅拷贝例子
    #include<iostream.h>
    #include<string.h>
    class Student {
    public:
        Student(char *name1,float score1);
        ~Student();
    private:
        char *name; // 学生姓名
        float score; // 学生成绩
    };
    Student∷Student(char *name1,float score1)
    {
        cout<<"Constructing..."<<name1<<endl;
        name=new char[strlen(name1)+1];
        if (name !=0)
        {
            strcpy(name,name1);
            score=score1;
        }
    }
    Student∷~Student()
    {
        cout<<"Destructing..."<<name<<endl;
        name[0]='';
        delete name;
    }
    void main()
    {
        Student stu1("liming",90); // 定义类Student的对象stu1
        Student stu2=stu1; // 调用缺省的拷贝构造函数
    }
    
    Constructing... liming
    Destructing... liming
    Destructing...
    

    浅拷贝示意图

    image

    例2.24 深拷贝例子
    #include<iostream.h>
    #include<string.h>
    class Student {
    private:
        char *name; // 学生姓名
        float score; // 学生成绩
    public:
        Student(char *name1,float score1);
        Student(Student& stu);
        ~Student();
    };
    Student∷Student(char *name1,float score1)
    {
        cout<<"constructing..."<<name1<<endl;
        name=new char[strlen(name1)+1];
        if (name !=0)
        {
            strcpy(name,name1);
            score=score1;
        }
    }
    Student∷Student(Student& stu)
    {
        cout<<"Copy constructing..."<<stu.name<<endl;
        name=new char[strlen(stu.name)+1];
        if (name !=0)
        {
            strcpy(name,stu.name);
            score=stu.score;
        }
    }
    Student∷~Student()
    {
        cout<<"Destructing..."<<name<<endl;
        name[0]='';
        delete name;
    }
    void main()
    {
        Student stu1("liming", 90); // 定义类Student的对象stu1,
        Student stu2=stu1; // 调用自定义的拷贝构造函数
    }
    
    Constructing…liming
    Copy constructing…liming
    Destructing…liming
    Destructing…liming
    

    深拷贝示意图

    image

    6. 析构函数

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

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

    • ① 析构函数与构造函数名字相同,但它前面必须加一个波浪号(~);
    • ② 析构函数没有参数,也没有返回值,而且不能重载。因此在一个类中只能有一个析构函数;
    • ③ 当撤消对象时,编译系统会自动地调用析构函数。 如果程序员没有定义析构函数,系统将自动生成和调用一个默认析构函数,默认析构函数只能释放对象的数据成员所占用的空间,但不包括堆内存空间。
    例2.25 重新说明类Date
    #include <iostream.h>
    class Date{
    public:
        Date(int y,int m,int d); // 构造函数
        ~Date(); // 析构函数
        void setDate(int y,int m,int d);
        void showDate();
    private:
        int year, month, day;
    };
    Date::Date(int y,int m,int d) // 构造函数的实现
    {
        cout<<"constructing..."<<endl;
        year=y;month=m; day=d;
    }
    Date::~Date() // 析构函数的实现
    { cout<<"destruting..."<<endl; }
    void Date::setDate(int y,int m,int d)
    { year=y;month=m;day=d; }
    inline void Date::showDate()
    { cout<<year<<"."<<month<<"."<<day<<endl; }
    void main()
    {
        Date date1(1998,4,28); // 定义类Date的对象date1,
        // 调用date1的构造函数,初始化对象date1
        cout<<"Date1 output1:"<<endl;
        date1.showDate(); // 调用date1的showDate(),显示date1的数据
        date1.setDate(2002,11,14); // 调用date1的setDate(),
        // 重新设置date1的数据
        cout<<"Date1 output2:"<<endl;
        date1.showDate(); // 调用date1的showDate(),显示date1的数据
    }
    

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

    1. 若一个对象被定义在一个函数体内,当这个函数结束时,析构函数被自动调用。
    2. 若一个对象是使用new运算符动态创建,在使用delete释放时,自动调用析构函数。
    【例2.13】 较完整的学生类例子
    #include<iostream.h>
    #include<string.h>
    class Student {
    public:
        Student(char *name1,char *stu_no1,float score1); // 构造
        函数
        ~Student(); // 析构函数
        void modify(float score1); // 修改数据
        void show(); // 显示数据
    private:
        char *name; // 学生姓名
        char *stu_no; // 学生学号
        float score; // 学生成绩
    };
    Student∷Student(char *name1,char *stu_no1,float score1)
    {
        name=new char[strlen(name1)+1];
        strcpy(name,name1);
        stu_no=new char[strlen(stu_no1)+1];
        strcpy(stu_no,stu_no1);
        score=score1;
    }
    Student∷~Student()
    {
        delete []name;
        delete []stu_no;
    }
    void Student∷modify(float score1)
    { score=score1; }
    void Student∷show()
    {
        cout<<"
     name: "<<name;
        cout<<"
     stu_no: "<<stu_no;
        cout<<"
     score: "<<score;
    }
    void main()
    {
        Student stu1("Liming","990201",90); // 定义类Student的对象stu1,
        // 调用stu1的构造函数,初始化对象stu1
        stu1.show(); // 调用stu1的show(),显示stu1的数据
        stu1.modify(88); // 调用stu1的modify(),修改stu1的数据
        stu1.show(); // 调用stu1的show(),显示stu1修改后的数据
    }
    
    name:Liming
    stu_no:990201
    score:90
    name:Liming
    stu_no:990201
    score:88
    

    缺省的析构函数

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

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

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

    class string_data {
    public:
        string_data(char *)
        { str=new char[max_len];}
        ~string_data()
        { delete []str;}
        void get_info(char *);
        void sent_info(char *);
    private:
        char *str;
        int max_len;
    };
    

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

    1) 一般顺序

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

    image

    2) 全局对象

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

    3) auto局部对象

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

    4) static局部对象

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

    8. 对象的生存期

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

    (1) 局部对象
    • 当对象被定义时,调用构造函数,该对象被创建;当程序退出该对象所在的函数体或程序块时,调用析构函数,对象被释放。
    • 局部对象是被定义在一个函数体或程序块内的,它的作用域限定在函数体或程序块内,生存期较短。
    (2) 全局对象
    • 当程序开始运行时,调用构造函数,该对象被创建;当程序结束时,调用析构函数,该对象被释放。
    • 静态对象是被定义在一个文件中,它的作用域从定义是起到文件结束时为止。生存期较长。
    (3) 静态对象
    • 当程序中定义静态对象时,调用构造函数,该对象被创建;当整个程序结束时,调用析构函数,对象被释放。
    • 全局对象是被定义在某个文件中,它的作用域包含在该文件的整个程序中,生存期是最长的。
    (4) 动态对象
    • 执行new运算符调用构造函数,动态对象被创建;用delete释放对象时,调用析构函数。
    • 动态对象是由程序员掌握的,它的作用域和生存期是由new和delete之间的间隔决定的。
    类的应用举例(例)

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

    #include <iostream>
    using namespace std;
    const float PI = 3.14159;
    const float FencePrice = 35;
    const float ConcretePrice = 20;
    //声明类Circle 及其数据和方法
    class Circle{
    private:
        float radius;
    public:
        Circle(float r); //构造函数
        float Circumference() const; //圆周长
        /*函数后的修饰符const表示该成员函数的执行不会改变类的状态,也就是说不会修改类的数据成员。 */
        float Area() const; //圆面积
    };// 类的实现
    // 构造函数初始化数据成员radius
    Circle::Circle(float r)
    {
        radius=r;
    }
    // 计算圆的周长
    float Circle::Circumference() const
    {
        return 2 * PI * radius;
    }
    // 计算圆的面积
    float Circle::Area() const
    {
        return PI * radius * radius;
    }
    void main ()
    {
        float radius;
        float FenceCost, ConcreteCost;
        
        // 提示用户输入半径
        cout<<"Enter the radius of the pool: ";
        cin>>radius;
        
        // 声明 Circle 对象
        Circle Pool(radius);
        Circle PoolRim(radius + 3);
        
        //计算栅栏造价并输出
        FenceCost=PoolRim.Circumference()*FencePrice;
        cout<<"Fencing Cost is ¥"<<FenceCost<<endl;
        
        //计算过道造价并输出
        ConcreteCost=(PoolRim.Area()-
        Pool.Area())*ConcretePrice;
        cout<<"Concrete Cost is ¥"<<ConcreteCost<<endl;
    }
    

    运行结果

    Enter the radius of the pool: 10
    Fencing Cost is ¥2858.85
    Concrete Cost is ¥4335.39
    
  • 相关阅读:
    场景法设计测试用例
    编写边界条件测试用例原则
    CSS
    JavaScript
    HTML
    lamp安装教程
    Linux(lamp安装)
    oracle sqlplus常用命令
    利用同步器实现互斥锁
    工厂模式--简单工厂模式
  • 原文地址:https://www.cnblogs.com/whale90830/p/10520316.html
Copyright © 2011-2022 走看看