1. 程式人生 > 實用技巧 >7_繼承與派生

7_繼承與派生

繼承與派生

  • 吸收基類成員
  • 改造基類成員
  • 新增派生類成員
class 派生類名:繼承方式 基類名
{
成員宣告;
}

class Derived: public Base
{
public:
	Derived ();
	~Derived ();
};

繼承方式

公有繼承

  • 基類的public和protected成員:訪問屬性在派生類中保持不變
  • 基類的private成員:不可直接訪問

型別轉換

公有派生類物件可以當作基類的物件使用(可以隱含轉換),反之不行。

但是轉換後,派生類只能使用從基類繼承來的成員。

派生類的構造和析構

一般自己寫新的建構函式,但c++11:使用using繼承基類的建構函式,但是隻能初始化從基類繼承的成員。

先基類引數初始化,再派生類引數初始

派生類名::派生類名(基類所需的形參,本類成員所需的形參):
基類名(引數表), 本類成員初始化列表
{
	//其他初始化;
};
    
#include<iostream>
using namespace std;
class B {
public:
    B();
    B(int i);
    ~B();
    void print() const;
private:
    int b;
};

B::B() {
    b=0;
    cout << "B's default constructor called." << endl;
}
B::B(int i) {
    b=i;
    cout << "B's constructor called." << endl;
}
B::~B() {
    cout << "B's destructor called." << endl;
}
void B::print() const {
    cout << b << endl;
}

class C: public B {
public:
    C();
    C(int i, int j);
    ~C();
    void print() const;
private:
    int c;
};
C::C() {
    c = 0;
    cout << "C's default constructor called." << endl;
}
C::C(int i,int j): B(i), c(j){
   cout << "C's constructor called." << endl;
}

複製建構函式

派生類未定義複製建構函式的情況

  • 編譯器會在需要時生成一個隱含的複製建構函式;
  • 先呼叫基類的複製建構函式;
  • 再為派生類新增的成員執行復制。

派生類定義了複製建構函式的情況

  • 一般都要為基類的複製建構函式傳遞引數。
  • 複製建構函式只能接受一個引數,既用來初始化派生類定義的成員,也將被傳遞給基類的複製建構函式。
  • 基類的複製建構函式形參型別是基類物件的引用,實參可以是派生類物件的引用
  • 例如: C::C(const C &c1): B(c1) {…}

解構函式

先派生類引數析構,再基類引數析構

  • 解構函式不被繼承,派生類如果需要,要自行宣告解構函式。
  • 宣告方法與無繼承關係時類的解構函式相同。
  • 不需要顯式地呼叫基類的解構函式,系統會自動隱式呼叫
  • 先執行派生類解構函式的函式體,再呼叫基類的解構函式。

派生類成員的訪問

一般是同名隱藏規則,但是也可以通過作用域操作符訪問

#include <iostream>
using namespace std;
class Base1 {   
public:
    int var;
    void fun() { cout << "Member of Base1" << endl; }
};
class Base2 {   
public:
    int var;
    void fun() { cout << "Member of Base2" << endl; }
};
class Derived: public Base1, public Base2 {
public:
    int var;    
    void fun() { cout << "Member of Derived" << endl; }
};

int main() {
    Derived d;
    Derived *p = &d;
  //訪問Derived類成員
    d.var = 1;
    d.fun();    
    //訪問Base1基類成員
    d.Base1::var = 2;
    d.Base1::fun(); 
    //訪問Base2基類成員
    p->Base2::var = 3;
    p->Base2::fun();    
    return 0;
}