一 应用场景
从基类派生一个子类可以为我们节省许多时间和工序,比如说假如我们为一个客户定做一个简易的售票系统,该系统被全面测试过,没有出现问题,客户也很满意,于是我们便将系统编译成可执行文件交付客户使用,但是随着时间的推移,客户又有了新的要求,他想要在这个售票系统中假如刷卡功能,但是在C++中,我们可以用继承来解决,我们只需要再派生一个基于售票系统的子类,在里面添加一个刷卡的功能就可以了,而基类的数据则完全不用改变
二 原因分析
继承固然为我们节省了不少时间和工序,但是由于子类是从基类派生出去的,因此我们在创建派生类的对象时,仍然需要对基类进行初始化。这个原因其实也不难理解,因为子类将基类的所有成员都继承了过去,所以被继承的成员也就会出现在子类里,那么我们在构造一个子类的对象时,难免就会调用基类的构造函数。
三 初始化方法
在创建派生类的构造函数时,有两种方法对数据进行初始化.
- 第一种:在派生类中创建一个构造函数,然后初始化所有数据(从基类那里继承来的数据和子类的数据)。这种方法显然是多余的,因为基类已经有了恰当的构造函数,为何还要重复构造呢。况且在派生类中对基类进行初始化的这种做法也是不可取的。
- 第二种:在派生类中创建一个构造函数,用该构造函数调用基类的构造函数并且向构造函数传递初始值。显然,第二种做法效率要高一些,并且出错的几率要小些
四 使用第一种方式演示及结果输出
4.1 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| #include<iostream> #include<string> using namespace std; class father { protected: string name; int tall; public: father(string a, int i); father() {cout << "构造基类" << endl;} ~father() {cout << "释放基类对象" << endl;} void print() {cout << "name:" << name << "身高为:" << tall << endl;} }; father::father(string a, int i) { cout << "在基类的构造函数内" << endl; name = a; tall = i; print(); cout << "离开基类的构造函数" << endl; } class son: public father { private: int weight; public: son(string a, int i, int j); void print1(); ~son() {cout << "释放子类对象" << endl;} }; son::son(string a, int i, int j) { name = a; tall = i; weight = j; cout << "在子类的构造函数内" << endl; } void son::print1() { father::print(); cout << "体重:" << weight << endl; } int main() { son Mike("Mike",180,80); Mike.print1(); cout<<"程序执行结束"<<endl; return 0; }
|
4.2 输出结果
1 2 3 4 5 6 7
| 构造基类 在子类的构造函数内 name:Mike身高为:180 体重:80 程序执行结束 释放子类对象 释放基类对象
|
五 使用第二种方式演示及结果输出
5.1 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| #include<iostream> #include<string> using namespace std; class father { protected: string name; int tall; public: father(string a, int i); father() {cout << "构造基类" << endl;} ~father() {cout << "释放基类对象" << endl;} void print() {cout << "name:" << name << "身高为:" << tall << endl;} }; father::father(string a, int i) { cout << "在基类的构造函数内" << endl; name = a; tall = i; print(); cout << "离开基类的构造函数" << endl; } class son: public father { private: int weight; public: son(string a, int i, int j); void print1(); ~son() {cout << "释放子类对象" << endl;} }; son::son(string a, int i, int j):father(a,i) { weight = j; cout << "在子类的构造函数内" << endl; } void son::print1() { father::print(); cout << "体重:" << weight << endl; } int main() { son Mike("Mike",180,80); Mike.print1(); cout<<"程序执行结束"<<endl; return 0; }
|
5.2 输出结果
1 2 3 4 5 6 7 8 9
| 在基类的构造函数内 name:Mike身高为:180 离开基类的构造函数 在子类的构造函数内 name:Mike身高为:180 体重:80 程序执行结束 释放子类对象 释放基类对象
|
六 总结
另外我们在使用第二种方式的时候要注意:
- 如果没有定义派生类的构造函数,那么将默认执行基类的构造函数
- 如果派生类要向基类传递参数,那么必须在派生类里定义一个构造函数,该函数只起向基类传递参数的作用
- 如果只需要调用基类的构造函数,不用向基类传递参数的话,那么派生类不用定义构造函数