欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

对象的构造与析构(二)

程序员文章站 2022-03-25 16:17:44
[TOC] 1. 析构函数 C++的类中可以定义一个特殊的清理函数,叫做析构函数,语法规则为 析构函数没有参数,也没有返回值类型声明 析构函数在对象销毁时自动被调用 当类中自定义了构造函数,并且构造函数中使用了系统资源(如:堆空间、文件打开,等),则需要自定义析构函数 2. 对象的构造与析构顺序 多 ......

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\n", 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\n", this);  //每个成员函数中隐藏了一个this指针,用于指向当前对象
}

int main()
{
    test t1(1);
    test t2(2);
    test t3(3);

    printf("t1.getmi() = %d\n", t1.getmi());
    printf("&t1 = %p\n", &t1);
    t1.print();

    printf("t2.getmi() = %d\n", t2.getmi());
    printf("&t2 = %p\n", &t2);
    t2.print();

    printf("t3.getmi() = %d\n", t3.getmi());
    printf("&t3 = %p\n", &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\n", 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\n", i, value);
        }
    }

    return 0;
}

对象的构造与析构(二)