【C++課程學習10】繼承
阿新 • • 發佈:2021-01-02
目錄
參考
- 範磊C++(第12課時)
筆記
繼承和派生的基本概念
- 什麼是繼承和派生
- 複雜的繼承和派生
- 繼承和派生如何在C++中實現?
派生型別(派生許可權)的概念,以後會講到。
單一繼承
只有一個基類
#include <iostream> using namespace std; class Father { private: int fatherHight,fatherWeight; public://建構函式只有一個引數,與下面的對應! void setFatherHight(int x){fatherHight=x;} void setFatherWeight(int x){fatherWeight=x;} void getFatherHightAndWeight(){cout<<"身高為"<<fatherHight<<endl; cout<<"體重為"<<fatherWeight<<endl;} }; class Son :public Father { private: int sonWidth,sonLong; public: void setSonHWidth(int x){sonWidth=x;} void setSonWLong(int x){sonLong=x;} void getsonHightAndWeight(){cout<<"肩寬為"<<sonWidth<<endl; cout<<"臂長為"<<sonLong<<endl;} }; int main(int argc, const char * argv[]) { Son LiMing; LiMing.setFatherHight(180); LiMing.setFatherWeight(80); LiMing.setSonWLong(134); LiMing.setSonHWidth(65); LiMing.getsonHightAndWeight(); LiMing.getFatherHightAndWeight(); return 0; }
輸出結果:
保護成員
#include <iostream> using namespace std; class Father { //private://子類不能訪問 protected://只能子類來訪問 int fatherHight,fatherWeight; public://建構函式只有一個引數,與下面的對應! void setFatherHight(int x){fatherHight=x;} void setFatherWeight(int x){fatherWeight=x;} //void getFatherHightAndWeight(){cout<<"身高為"<<fatherHight<<endl; // cout<<"體重為"<<fatherWeight<<endl;} }; class Son :public Father { private: int sonWidth,sonLong; public: void setSonHWidth(int x){sonWidth=x;} void setSonWLong(int x){sonLong=x;} //void getsonHightAndWeight(){cout<<"肩寬為"<<sonWidth<<endl; // cout<<"臂長為"<<sonLong<<endl;} void PrintAll(){ cout<<"肩寬為"<<sonWidth<<endl; cout<<"臂長為"<<sonLong<<endl; cout<<"身高為"<<fatherHight<<endl; cout<<"體重為"<<fatherWeight<<endl; } }; int main(int argc, const char * argv[]) { Son LiMing; LiMing.setFatherHight(180); LiMing.setFatherWeight(80); LiMing.setSonWLong(134); LiMing.setSonHWidth(65); //LiMing.getsonHightAndWeight(); //LiMing.getFatherHightAndWeight(); LiMing.PrintAll(); return 0; }
輸出結果:
共有派生
-
共有
-
保護
-
私有
繼承的賦值
子類可以賦值給父類,但父類不能給子類。
因為父類的成員數少。
同樣,基類的指標可以指向派生類物件,但是派生類指標不能指向基類物件。
私有派生(繼承)
#include <iostream> using namespace std; class Father { public: void room(){cout<<"父親的大房子我可以享受"<<endl;} };//注意分號 class Son: private Father { public: void enjoy(){room();} }; int main(int argc, const char * argv[]) { Son a; a.enjoy(); return 0; }
輸出結果:
多重繼承
#include <iostream>
using namespace std;
class Father
{
public:
void setA(int a ){tall=a;}
void print1(){cout<<"身高的值:"<<tall<<endl;}
private:
int tall;
};
class Mother
{
public:
void setB(int a ){weight=a;}
void print2(){cout<<"體重的值:"<<weight<<endl;}//成員函式名字最好不要相同,否則會報錯!
private:
int weight;
};
class Son: public Father,public Mother
{
public:
void setC(int a ){age=a;}
void print3(){print1();print2();cout<<"年齡的值:"<<age<<endl;}
private:
int age;
};
int main(int argc, const char * argv[]) {
Son Mike;
Mike.setA(175);
Mike.setB(80);
Mike.setC(25);
Mike.print3();
return 0;
}
輸出:
當然同樣的也可以設定派生許可權。
繼承的構造與構析
建構函式和解構函式的執行順序。
基類的構造順序是按繼承時的給定順序執行。
析構時則正好相反。
向基類建構函式傳遞引數
- 方法1
方法正確,但是呼叫父類的建構函式對建立子類物件沒有幫助,( 無用的建構函式)這相當於浪費了系統的開銷。
#include <iostream>
#include<string>
using namespace std;
class Father
{
public:
Father(){cout<<"構造基類物件"<<endl;}
~Father(){cout<<"析構基類物件"<<endl;}
void setA(int a ){tall=a;}
void print(){cout<<name<<"身高的值:"<<tall<<"cm"<<endl;}
protected:
string name;
int tall;
private:
};
class Son :public Father
{
public:
Son(string a, int i, int j){
name=a;
tall=i;
weight=j;
cout<<"構造子類物件"<<endl;}
~Son(){cout<<"析構子類物件"<<endl;}
void setA(int a ){tall=a;}
void print1(){print();cout<<"體重的值:"<<weight<<"kg"<<endl;}//不能覆蓋掉父類的,因此要改名。
protected:
int weight;
private:
};
int main(int argc, const char * argv[]) {
Son Mike("Mike",180,80);
Mike.print1();
cout<<"程式結束"<<endl;
return 0;
}
輸出:
- 方法2
充分利用基類的建構函式。
#include <iostream>
#include<string>
using namespace std;
class Father
{
public:
//Father(){cout<<"構造基類物件"<<endl;}
Father(string a, int i){
name=a;
tall=i;
cout<<"構造帶兩個引數的基類物件"<<endl;}
~Father(){cout<<"析構基類物件"<<endl;}
void setA(int a ){tall=a;}
void print(){cout<<name<<"身高的值:"<<tall<<"cm"<<endl;}
protected:
string name;
int tall;
private:
};
class Son :public Father
{
public:
Son(string a, int i, int j):Father(a,i){
weight=j;
cout<<"構造子類物件"<<endl;}
~Son(){cout<<"析構子類物件"<<endl;}
void setA(int a ){tall=a;}
void print1(){print();cout<<"體重的值:"<<weight<<"kg"<<endl;}//不能覆蓋掉父類的,因此要改名。
protected:
int weight;
private:
};
int main(int argc, const char * argv[]) {
Son Mike("Mike",180,80);//
Mike.print1();
cout<<"程式結束"<<endl;
return 0;
}
輸出:
多重繼承容易產生兩義性
成員重名導致的問題。
會產生警告⚠️
強行執行的話,就會產生覆蓋問題。
可以使用作用域操作符來避免這個問題。
兩義性的歸屬問題
繼承中的過載
一旦子類定義了建構函式,基類中的建構函式就會被覆蓋。
【問題】const函式,只能由const物件呼叫嗎???