C++构造与析构-10

一。对象的初始化

  1.一般所有的对象都需要一个确定的初始状态

  2.解决方案

    a。为每个类偶读提供一个public的initialize函数

    b。对象创建后立即调用initialize函数进行初始化

#include<stdio.h>

class Test
{
    private:
       int i;
    public:
       void initialize()
       {    
            i = 0;    
        }    
        int get1()
        {
            return i;
        }
};

int main()
{
    Test t1;
    Test t2;
    Test t3;
    
    t1.initialize();
    t2.initialize();
    t3.initialize();
    
    printf("ti.i = %d
",t1.get1());
    printf("ti.i = %d
",t1.get1());
    printf("ti.i = %d
",t1.get1());
    
    printf("Press any key to continue");
    getchar();
    return 0;    
}

  3.initialize只是一个普通的函数,必须显示的调用

  4.一旦由于失误的原因,对象没有初始化,那么结果将是不确定的

    没有初始化的对象,其内部成员变量的值是不变的。

二。 C++中的构造函数

  1. C++中的类可以定义与类名相同的特殊成员函数。

  2.这种与类名相同的成员函数叫做构造函数

  3.构造函数在定义时可以有参数,但是没有任何返回类型的声明 

  4.构造函数的调用

    a。一般情况下C++编译器会自动调用构造函数

    b。一些情况下需要手工调用的函数

#include<stdio.h>

class Test
{
    private:
       int i;
       int j;
       int k; 
    public:
        Test(int v)
        {
            i = j = k = v;    
        }
        void print()
        {
            printf("i = %d,j = %d,k = %d
",i,j,k);    
        }
};

int main()
{
    Test t1(4);
    Test t2 = 5;
    Test t3 = Test(6);;
    
    
    t1.print();
    t2.print();
    t3.print();
    
    Test tA[3] = {Test(1),Test(2),Test(3)};
    for(int i=0;i<3;i++)
    {
        tA[i].print();
    }
    
    printf("Press any key to continue");
    getchar();
    return 0;    
}

  5.两个特殊的构造函数

#include<stdio.h>
/*
  注意:
   1.当类中没有定义任何构造函数,C++编译器会提供一个无参构造函数和拷贝构造函数
   2.当类中定义了任意的非拷贝构造函数时,C++编译器不会为我们提供无参构造函数
*/ class Test { private: int i; int j; int k; public: Test(const Test& v) { printf("Test(const Test& v) "); } Test() { printf("Test() "); } }; int main() { Test t1; Test t2 = t1; printf("Press any key to continue"); getchar(); return 0; }

  a.无参构造函数

    当类中没有定义构造函数时,编译器默认会提供一个无参构造函数,并且其函数体为空

  b.拷贝构造函数

    当类中没有定义拷贝构造函数时,编译器默认提供一个拷贝构造函数,简单的进行成员变量的值复制

三。数组类

  array.h  

#ifndef _ARRAY_H_
#define _ARRAY_H_

class Array
{
private:
   int mLength;
   int* mSpace;
 
public:
   Array(int length);
   Array(const Array& obj);
   int length();
   void setData(int index,int value);
   int  getData(int index);  
   void destory();  
  ~Array(); };
#endif

  array.c

#include"array.h"

Array::Array(int length) //数组创建 
{
    if(length < 0)
    {
        length = 0;
    }
    mLength = length;    
    mSpace = new int[mLength];
}
Array::Array(const Array& obj)
{
    mLength = obj.mLength;
    mSpace = new int[mLength];   
    
    for(int i=0; i<mLength; i++)
    {
        mSpace[i] = obj.mSpace[i];
    } 
}
int Array::length() //数组大小 
{
    return mLength;    
}

void Array::setData(int index,int value)//设置数组值 
{
    mSpace[index] = value;   
}

int Array::getData(int index)      //获取数组值 
{
    return mSpace[index];
}
Array::~Array() //销毁空间 { mLength = -1; delete[] mSpace; }

  main.c

#include<stdio.h>
#include "array.h"

int main()
{
    Array a1(10);
    for(int i=0; i<a1.length();i++)
    {
        a1.setData(i,i); 
    }
    
    for(int i=0; i<a1.length();i++)
    {
        printf("element %d: %d
",i,a1.getData(i));
    }
    
    Array a2 = a1;
    
    for(int i=0; i<a2.length();i++)
    {
        printf("element1 %d: %d
",i,a2.getData(i));
    }
    
    printf("Press any key to continue");
    getchar();
    return 0;    
}

  输出结果

  

四。初始化列表的使用

#include <cstdlib>
#include <cstdio>
#include <iostream>

using namespace std;
class M
{
    private:
        int mI;
    public:
        M(int i)
        {
            printf("M(int i),i =%d
",i);
            mI = i;    
        }
        int getI()
        {
            return mI;   
        }
};

class Test
{
    private:
        const int c;
        M m1;
        M m2;  
    public:
        Test():c(1),m1(2),m2(3)
        {
            printf("getI()
");    
        }
        void print()
        {
            printf("c = %d,m1.mI= %d,m2.mI = %d
",c,m1.getI(),m2.getI());    
        }
};
void run()
{
    Test t1;    
    t1.print();
}

int main(int argc, char *argv[])
{
    run();
    cout << "Press the enter key to continue ...";
    cin.get();
    return EXIT_SUCCESS;
}

  1.初始化列表对成员变量进行初始化 

    语法规则:

    Constructor::Constructor():m1(v1),m2(v2),m3(v3)

    {

    }

   注意:成员变量的初始化顺序与声明的顺序有关,与在初始化列表中的顺序无关。

      初始化列表优先于构造函数的函数体去执行

五。对象的销毁

  1.destroy 只是一个普通的函数,必须显示的调用

  2.如果对象销毁没有清理,就会发生内存泄露

六。析构函数

  1.c++类中可以定义一个特殊的成员函数清理对象

  2.这个特殊的函数叫做析构函数

    定义 ~ClassName()

  3.析构函数没有参数也没有任何返回类型的声明

  4.析构函数在对象销毁时自动被调用

#include <cstdlib>
#include <cstdio>
#include <iostream>

using namespace std;

class Test
{ 
    private:
        int mI;
    public:
        Test(int i):mI(i)
        {
            printf("test(),mI = %d
",mI);    
        }
        ~Test()
        {
            printf("~test(),mI = %d
",mI);    
        }
};
void run()
{
    Test t1(1);
    Test t2(2);    
}

int main(int argc, char *argv[])
{
    run();
    cout << "Press the enter key to continue ...";
    cin.get();
    return EXIT_SUCCESS;
}

六。构造与析构

  1.构造函数与析构函数的调用秩序

   当类中有成员变量是其他类的对象时:

    a。首先调用成员变量的构造函数

      调用顺序与声明顺序相同

#include <stdio.h>

class Test
{
private:
    int mI;
public:
    Test()
    {
        printf("Test()
");
        mI = -1;
    }
    
    Test(int i)
    {
        printf("Test(int i), i = %d
", i);
        mI = i;
    }
    
    Test(const Test& obj)
    {
        printf("Test(const Test& obj), i = %d
", obj.mI);
        mI = obj.mI;
    }
    
    ~Test()
    {
        printf("~Test(), i = %d
", mI);
    }
};

void func(Test t)
{
    Test r(1);
}

void run()
{
    Test t(0);
    
    func(t);
}

int main()
{
    run();
    
    printf("Press any key to continue...");
    getchar();
    return 0;
}
#include <stdio.h>

class Test
{
private:
    int mI;
public:
    Test()
    {
        printf("Test()
");
        mI = -1;
    }
    
    Test(int i)
    {
        printf("Test(int i), i = %d
", i);
        mI = i;
    }
    
    Test(const Test& obj)
    {
        printf("Test(const Test& obj), i = %d
", obj.mI);
        mI = obj.mI;
    }
    
    ~Test()
    {
        printf("~Test(), i = %d
", mI);
    }
};

void func(Test t)
{
    Test r(1);
}

void run()
{
    Test t(0);
    
    func(t);
}

int main()
{
    run();
    
    printf("Press any key to continue...");
    getchar();
    return 0;
}

   b。之后调用自身类的构造函数

   析构函数的调用秩序与对应的构造函数调用秩序相反

七。小结

  1.析构函数是C++中对象销毁是做清理工作的特殊函数

  2.析构函数在对象销毁时自动被调用

  3.析构函数对象所使用的资源及时释放的保障

  4.析构函数的调用秩序与析构函数相反

原文地址:https://www.cnblogs.com/lvxiaoning/p/7589310.html