第9课 - 构造函数
一.对象的初始化
1.1 对每个类都提供一个public的initialize函数
对象创建后立即调用initialize函数进行初始化Source Example 1.1: #include <iostream> /* run this program using the console pauser or add your own getch, system("pause") or input loop */ class Test { private: int i; public: void initialize() { i = 0; } int geti() { return i; } }; int main(int argc, char** argv) { Test test1; test1.initialize(); /* 输出结果为0 */ printf ("%d\n", test1.geti()); return 0; }方案缺点:
initialize只是一个普通的函数,必须显示的调用。
一旦由于失误的原因,对象没有初始化,那么结果将是不确定的。
1.2 C++中的构造函数
1.2.1 C++中的类可以定义与类名相同的特殊成员函数
1.2.2 这种类名相同的成员函数叫做构造函数
1.2.3 构造函数在定义时可以有参数,但是没有任何返回类型的声明(与返回值为void完全不同)
1.2.4 一般情况下C++编译器会自动调用构造函数,在一些情况下则需要手工调用
Source Example 1.2: #include <iostream> /* run this program using the console pauser or add your own getch, system("pause") or input loop */ class Test { private: int i; int j; int k; public: Test (int v) /* 构造函数 */ { i = j = k = v; } int print() { printf ("i = %d, j = %d, k = %d\n", i,j,k); } }; int main(int argc, char** argv) { Test test1(4); /* 自动初始化 */ Test test2 = 5; /* 自动初始化 */ Test test3 = Test(6); /* 手动初始化 */ /* 输出结果为: i = 4,j = 5,k = 6 i = 4,j = 5,k = 6 i = 4,j = 5,k = 6 */ test1.print(); test2.print(); test3.print(); /* 定义了类的对象数组,必须手动初始化,否则编译报错 */ Test tA[3] = {Test(1), Test(2),Test(3)}; for (int i = 0; i < 3; i++) { /* 输出结果为: i = 1,j = 2,k = 3 i = 1,j = 2,k = 3 i = 1,j = 2,k = 3 */ tA[i].print(); } return 0; }
1.3 成员函数的重载
1.3.1 类的成员函数和普通函数一样可以重载,并遵守相同的重载规则
1.3.2 构造函数也是成员函数,也可以进行重载
Source Example 1.3: #include <iostream> /* run this program using the console pauser or add your own getch, system("pause") or input loop */ class Test { private: int i; int j; int k; public: Test (int v) { i = j = k = v; } Test () { i = 0; j = 0; k = 0; } int print() { printf ("i = %d, j = %d, k = %d\n", i,j,k); } int print(int v) { printf ("v = %d\n", v); } }; int main(int argc, char** argv) { /* 会调用一个参数的构造函数来初始化 */ Test test1(4); Test test2 = 5; Test test3 = Test(6); Test test4; /* 会调用没有参数的函数来初始化 */ /* 输出结果为: i = 4,j = 5,k = 6 i = 4,j = 5,k = 6 i = 4,j = 5,k = 6 i = 0,j = 0,k = 0 */ test1.print(); test2.print(); test3.print(); test4.print(); /* 编译通过了,会调用没有参数的构造函数进行初始化 */ Test tA[3]; for (int i = 0; i < 3; i++) { /* 输出结果为: i = 0,j = 0,k = 0 i = 0,j = 0,k = 0 i = 0,j = 0,k = 0 */ tA[i].print(); } return 0; }
1.4 两个特殊的构造函数
1.4.1 拷贝构造函数(参数为const引用)
当类中没有定义拷贝构造函数时,编译器默认提供一个拷贝构造函数,简单的进行成员变量的复制1.4.2 默认构造函数(没有参数)
当类中没有定义构造函数时,编译器默认提供一个无参构造函数,并且其函数体为空当自己写了任意一个构造函数之后,编译器就不会提供无参构造函数了
Source Example 1.4.1: #include <iostream> /* run this program using the console pauser or add your own getch, system("pause") or input loop */ class Test { public: Test (const int& v) { printf ("const int& v!\n"); } Test () { printf ("no paramts!\n"); } /* 当使用该函数时,编译不过,因为编译器就不会提供默认构造函数,Test t1;在定义时没有提供初始化参数,就会出错 Test (int v) { } */ }; int main(int argc, char** argv) { /* 输出结果为 no paramts! const int& v! */ Test t1; Test t2 = 5; return 0; }注意:
1.当类中没有定义任何一个构造函数,C++编译器会为我们提供无参构造函数和拷贝构造函数
2.当类中定义了任意非拷贝构造函数时,C++编译器就不会为我们提供无参构造函数
Source Example 1.4.2: #include <iostream> /* run this program using the console pauser or add your own getch, system("pause") or input loop */ class Test { private: int i; int j; int k; public: void print() { printf("i = %d, j = %d, k = %d\n", i, j , k); } }; int main(int argc, char** argv) { Test t1; Test t2 = t1; /* 会调用拷贝构造函数将t1成员变量的值拷贝给t2的成员变量 */ /* 输出结果为: i = 2031646, j = 0, k = 1 i = 2031646, j = 0, k = 1*/ t1.print(); t2.print(); return 0; }
二.数组类的创建
Source Example 2: /* array.h */ #ifndef _ARRAY_H_ #define _ARRAY_H_ class Array{ private: int iLength; int *pSpace; public: Array(int length); int getLength(); void setData(int index, int data); int getData(int index); int destroy(); }; #endif /* _ARRAY_H_ */ /* array.c */ #include "array.h" Array :: Array(int length) { iLength = length; if (length > 0) { pSpace = new int[length]; } } int Array :: getLength() { return iLength; } void Array :: setData(int index, int data) { pSpace[index] = data; } int Array :: getData(int index) { return pSpace[index]; } /* 自己提供的拷贝构造函数,具体原因见下列代码注释 */ Array :: Array(const Array& obj) { iLength = obj.iLength; pSpace = new int[iLength]; for (int i = 0; i < iLength; i++) { pSpace[i] = obj.pSpace[i]; } } int Array :: destroy() { length = -1; delete[] pSpace; } #include <iostream> #include "array.h" /* run this program using the console pauser or add your own getch, system("pause") or input loop */ int main(int argc, char** argv) { Array a(10); for (int i = 0; i < 10; i++) { a.setData(i, i); } for (int j = 0; j < a.getLength(); j++) { printf ("%d\n", a.getData(j)); } /* 通过构造函数将a的成员变量全部赋值给a2 */ /* 包括iLength,pSpace指向了同一片空间 */ Array a2 = a; for (int j = 0; j < a2.getLength(); j++) { printf ("%d\n", a2.getData(j)); } /* 释放空间的时候只能调用一个销毁函数,否则就会出错,解决方法就是自己提供一个拷贝构造函数 */ a.destroy(); a2.destroy(); return 0;