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\n",t1.get1()); printf("ti.i = %d\n",t1.get1()); printf("ti.i = %d\n",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\n",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)\n"); } Test() { printf("Test()\n"); } }; 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\n",i,a1.getData(i)); } Array a2 = a1; for(int i=0; i<a2.length();i++) { printf("element1 %d: %d\n",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\n",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()\n"); } void print() { printf("c = %d,m1.mI= %d,m2.mI = %d\n",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\n",mI); } ~Test() { printf("~test(),mI = %d\n",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()\n"); mI = -1; } Test(int i) { printf("Test(int i), i = %d\n", i); mI = i; } Test(const Test& obj) { printf("Test(const Test& obj), i = %d\n", obj.mI); mI = obj.mI; } ~Test() { printf("~Test(), i = %d\n", 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()\n"); mI = -1; } Test(int i) { printf("Test(int i), i = %d\n", i); mI = i; } Test(const Test& obj) { printf("Test(const Test& obj), i = %d\n", obj.mI); mI = obj.mI; } ~Test() { printf("~Test(), i = %d\n", 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.析构函数的调用秩序与析构函数相反