• 对象的构造与析构(二)


    1. 析构函数

    • C++的类中可以定义一个特殊的清理函数,叫做析构函数,语法规则为~ClassName()
    • 析构函数没有参数,也没有返回值类型声明
    • 析构函数在对象销毁时自动被调用
    • 当类中自定义了构造函数,并且构造函数中使用了系统资源(如:堆空间、文件打开,等),则需要自定义析构函数

    2. 对象的构造与析构顺序

    多个对象之间

    多个对象构造时:

    • 栈对象的构造顺序依赖于程序的执行流
    • 堆对象的构造顺序依赖于new的使用顺序
    • 全局对象的构造顺序是不确定的,不同的编译器可能使用不同的规则

    多个对象析构时:

    • 栈对象和全局对象的析构顺序与构造顺序相反
    • 堆对象的析构发生取决于delete的使用顺序

    单个对象内部

    单个对象创建时,对象内部构造函数的调用顺序为:

    • 先调用父类的构造函数
    • 再调用成员变量的构造函数,调用顺序与声明顺序相同
    • 最后调用类自身的构造函数

    单个对象内部的析构顺序与构造顺序相反。

    3. const对象与const成员函数

    const对象

    • 由const关键字修饰的对象为只读对象
    • 只读对象的成员变量不允许被改变
    • 只读属性只在编译阶段有效,运行时无效

    const成员函数

    const成员函数的定义如下所示,需要注意的是,函数声明和函数定义都必须带const关键字。

    Type ClassName :: func(Type para) const
    

    关于const成员函数的使用,有下面几条规则:

    • const对象只能调用const成员函数
    • const成员函数只能调用const成员函数
    • const成员函数不能直接修改成员变量的值
    #include <stdio.h>
    
    class Test
    {
        int mi;
    public:
        Test(int i);
        void setMi(int i) const;
        int getMi() const;
        void printMi();
    };
    
    Test::Test(int i)
    {
        mi = i;
    }
    
    void Test::setMi(int i) const
    {
        mi = i;  //Error,const成员函数中不能直接修改成员变量的值
    }
    
    int Test::getMi() const
    {
        return mi;
    }
    
    void Test::printMi()
    {
        printf("printMi(): mi = %d
    ", mi);
    }
    
    int main()
    {
        const Test t1(1);
    
        t1.getMi();    //OK,const对象调用const成员函数
        t1.printMi();  //Error,const对象调用普通成员函数
    
        return 0;
    }
    

    4. 成员函数、成员变量与对象的关系

    面向对象的角度,对象由属性(成员变量)方法(成员函数)构成;
    程序运行的角度,对象由数据函数构成,数据位于栈、堆或全局数据区,函数位于代码段。

    • 每一个对象都拥有自己独立的属性(成员变量)
    • 所有的对象共享类的方法(成员函数)
    • 方法能够直接访问对象的属性
    • 方法中的隐藏参数this指针用于值代当前对象
    #include <stdio.h>
    
    class Test
    {
        int mi;
    public:
        int mj;
        Test(int i);
        Test(const Test &t);
        int getMi();
        void print();
    };
    
    Test::Test(int i)
    {
        mi = i;
    }
    
    Test::Test(const Test &t)
    {
        mi = t.mi;  //成员函数可以直接访问对应类对象的成员变量
    }
    
    int Test::getMi()
    {
        return mi;
    }
    
    void Test::print()
    {
        printf("this = %p
    ", this);  //每个成员函数中隐藏了一个this指针,用于指向当前对象
    }
    
    int main()
    {
        Test t1(1);
        Test t2(2);
        Test t3(3);
    
        printf("t1.getMi() = %d
    ", t1.getMi());
        printf("&t1 = %p
    ", &t1);
        t1.print();
    
        printf("t2.getMi() = %d
    ", t2.getMi());
        printf("&t2 = %p
    ", &t2);
        t2.print();
    
        printf("t3.getMi() = %d
    ", t3.getMi());
        printf("&t3 = %p
    ", &t3);
        t3.print();
    
        return 0;
    }
    

    5. 代码实战——数组类IntArray

    IntArray.h

    #ifndef _INTARRAY_H_
    #define _INTARRAY_H_
    
    class IntArray
    {
    private:
        int m_length;
        int *m_pointer;
    public:
        IntArray(int len);
        IntArray(const IntArray &obj);
        int length();
        bool get(int index, int &value);
        bool set(int index ,int value);
        ~IntArray();
    };
    
    #endif
    

    IntArray.cpp

    #include "IntArray.h"
    
    IntArray::IntArray(int len)
    {
        m_pointer = new int[len];
    
        for(int i=0; i<len; i++)
        {
            m_pointer[i] = 0;
        }
    
        m_length = len;
    }
    
    IntArray::IntArray(const IntArray &obj)
    {
        m_length = obj.m_length;
    
        m_pointer = new int[obj.m_length];
    
        for(int i = 0; i < obj.m_length; i++)
        {
            m_pointer[i] = obj.m_pointer[i];
        }
    }
    
    int IntArray::length()
    {
        return m_length;
    }
    
    bool IntArray::get(int index, int &value)
    {
        bool ret = (0 <= index) && (index < length());
    
        if( ret )
        {
            value = m_pointer[index];
        }
    
        return ret;
    }
    
    bool IntArray::set(int index, int value)
    {
        bool ret = (0 <= index) && (index < length());
    
        if( ret )
        {
            m_pointer[index] = value;
        }
    
        return ret;
    }
    
    IntArray::~IntArray()
    {
        delete[] m_pointer;
    }
    

    IntArray测试

    #include "IntArray.h"
    #include <stdio.h>
    
    int main()
    {
        IntArray a(5);
    
        for(int i = 0; i < a.length(); i++)
        {
            a.set(i, i + 1);
        }
    
        for(int i = 0; i < a.length(); i++)
        {
            int value = 0;
    
            if( a.get(i, value) )
            {
                printf("a[%d] = %d
    ", i, value);
            }
        }
    
        IntArray b = a;
    
        for(int i = 0; i < b.length(); i++)
        {
            int value = 0;
    
            if( b.get(i, value) )
            {
                printf("b[%d] = %d
    ", i, value);
            }
        }
    
        return 0;
    }
    

  • 相关阅读:
    Openssl命令详解
    Openssl命令详解
    Mac根目录下无法创建文件或目录
    解决 mysql from_base64 函数返回乱码的问题
    elementUI日期选择器 el-date-picker根据所选日期选择禁用
    el-dialog设置为点击弹窗以外的区域不自动关闭弹窗
    在vue项目中MD5加密的使用方法
    bower install 报错fatal: unable to access 'https://github.com/angular/bower-angular-touch.git/'类错误解决方法
    angular项目grunt serve报错Cannot find where you keep your Bower packages
    移动端开发--》适配各种机型样式大小
  • 原文地址:https://www.cnblogs.com/songhe364826110/p/11546138.html
Copyright © 2020-2023  润新知