簡單來說:有兩個(gè)類A和B,A是父類,B是子類。那么就可以說:A派生出B,B繼承與A。
例:
父親 “派生” 出兒子
兒子 “繼承” 自父親
派生和繼承,本質(zhì)是相同的,只是從不同角度來描述他們而已。
繼承和派生在UML中的表示:
注意是空心三角形
從 子類【派生的類】 指向 父類【被繼承的類】
父類,也被稱為 ”基類”
除了 ”構(gòu)造函數(shù)“ 和 ”析構(gòu)函數(shù)“,
父類的所有成員函數(shù),以及數(shù)據(jù)成員,都會(huì)被子類繼承!
假如已經(jīng)定義好了父類Father
,里面定義好私有數(shù)據(jù)成員name
和age
,和公有的構(gòu)造函數(shù)、成員方法description
等。當(dāng)子類Son
要繼承父類Father
時(shí),需要包含 ”父類的頭文件“,定義方式如下:
公有繼承方式
#include "Father.h" // 包含父類的頭文件class Son : public Father { // 詳細(xì)見下面全部代碼}
假如子類Son要調(diào)用自定義的重載構(gòu)造函數(shù)是:
1.會(huì)先調(diào)用父類的構(gòu)造函數(shù),用來初始化父類繼承的數(shù)據(jù),
2.再掉用自己的構(gòu)造函數(shù),用來初始化自己定義的數(shù)據(jù)。
例:
Son::Son(const char *name, int age, const char *game) : Father(name, age) { // 沒有體現(xiàn)父類的構(gòu)造函數(shù), 那就會(huì)自動(dòng)調(diào)用父類的默認(rèn)構(gòu)造函數(shù)!!! this->game = game; // 子類自己定義的數(shù)據(jù)成員}
注意一:
子類的成員函數(shù),不能訪問從父類繼承的private成員
例:
在子類Son中,this->name = name;
或者 cout << age << endl;
都是錯(cuò)誤的。
但子類可以訪問父類的成員函數(shù),如 cout << getName() << getAge() << endl;
都是正確的。
注意二:
子類對(duì)象調(diào)用方法時(shí),現(xiàn)在自己定義的方法中去尋找,如果有,就調(diào)用自己定義的方法;如果找不到,就到父類的方法中去找,如果有,就調(diào)用父類的這個(gè)同名方法;如果在父類中找不到,就發(fā)生錯(cuò)誤!
例:
父類和子類都定義了description
方法,子類Son
去調(diào)用這個(gè)方法,會(huì)優(yōu)先在自己的方法里去找來調(diào)用,如果沒有,再去父類里找;也沒有的話就報(bào)錯(cuò)。
Son son("王思聰", 32, "電競"); cout << son.description() << endl;
============================================================
繼承和派生的簡單說明完結(jié),具體代碼如下:
代碼實(shí)現(xiàn):
定義Father
父類
#pragma once#include <string>using namespace std;class Father {public: Father(const char *name, int age); ~Father(); string getName() const; int getAge() const; string description() const;private: string name; int age;};
Father
類方法實(shí)現(xiàn)
#include <sstream> // 不懂此類型,請看我另一篇博客介紹#include "Father.h"Father::Father(const char *name, int age) { this->name = name; this->age = age;}Father::~Father() {}string Father::getName() const { return name;}int Father::getAge() const { return age;}string Father::description() const { stringstream ret; // 不懂此類型,請看我另一篇博客介紹 ret << "姓名:" << name << " 年齡:" << age << endl; return ret.str();}
定義Son
子類
#pragma once#include "Father.h"class Son : public Father {public: Son(const char *name, int age, const char *game); ~Son(); string getGame() const; string description() const;private: string game;};
Son
方法實(shí)現(xiàn)
#include <sstream> // 不懂此類型,請看我另一篇博客介紹#include "Son.h"// 創(chuàng)建Son對(duì)象時(shí), 會(huì)調(diào)用構(gòu)造函數(shù)!// 會(huì)先調(diào)用父類的構(gòu)造函數(shù), 用來初始化從父類繼承的數(shù)據(jù) // 再調(diào)用自己的構(gòu)造函數(shù), 用來初始化自己定義的數(shù)據(jù)Son::Son(const char *name, int age, const char *game) : Father(name, age) { // 沒有體現(xiàn)父類的構(gòu)造函數(shù), 那就會(huì)自動(dòng)調(diào)用父類的默認(rèn)構(gòu)造函數(shù)!!! this->game = game;}Son::~Son() {}string Son::getGame() const { return game;}string Son::description() const { stringstream ret; // 不懂此類型,請看我另一篇博客介紹 /* // 下面都是錯(cuò)誤的 this->name = name; this->age = age; cout << name << age << endl; */ // 子類的成員函數(shù)中, 不能訪問從父類繼承的private成員 ret << "name:" << getName() << " age:" << getAge() << " game:" << game << endl; return ret.str();}
main方法實(shí)現(xiàn):
#include <iostream>#include "Father.h"#include "Son.h"int main(void) { Father father("王健林", 68); Son son("王思聰", 32, "電競"); cout << father.description() << endl; // 子類對(duì)象調(diào)用方法時(shí), 先在自己定義的方法中去尋找, 如果有, 就調(diào)用自己定義的方法 // 如果找不到, 就到父類的方法中去找, 如果有, 就調(diào)用父類的這個(gè)同名方法 // 如果還是找不到, 就是發(fā)生錯(cuò)誤! cout << son.description() << endl; system("pause"); return 0;}
運(yùn)行截圖:
子類, 一般會(huì)添加自己的數(shù)據(jù)成員/成員函數(shù),
或者, 重新定義從父類繼承的方法!!! 子類對(duì)象就會(huì)調(diào)用自己重新定義的方法, 不會(huì)調(diào)用父類的同名方法
聯(lián)系客服