C++03:封裝->繼承->多態

一.簡介

1.可維護ios

2.可複用編程

3.可擴展ide

4.靈活性好函數

面向對象的設計思想就是經過封裝 繼承 多態把程序的耦合性下降,使得程序更加的靈活,容易修改,而且易於複用測試

 

面向對象的五大基本原則

1.單一職責原則(SRP)

2.開放封閉原則(OCP)

3.里氏替換原則(LSP)

4.依賴倒置原則(DIP)

5.接口隔離原則(ISP)

 

函數編程

泛型編程

元編程

 

二.封裝

class A{
  
public:
    A(int a){
  
    }
}

 

1.重載(Overload)

 成員被重載的特徵:(1)相同的範圍,在同一個類中

                                 (2)函數名字相同

                                 (3)參數不一樣spa

 

2.抽象類和純虛函數

純虛函數是在基類聲明的虛函數(加上 =0),它在基類中沒有定義,可是要求派生類都要實現本身的實現方法設計

包含純虛函數的類稱爲抽象類指針

(1) 抽象類只能用做其餘類的基類,不能定義抽象類的對象code

(2) 抽象類不能用於參數類型 函數返回值 或 顯示轉換的類型對象

(3) 抽象類能夠定義抽象類的指針和引用,此指針能夠指向它的派生類,進而實現多態性

 

三.繼承

class B: public A{
public:
    B(int a,int b):A(a){
  
    }
};
  
class C:public A{
public:
    C(int a,int c):A(a){
     
    }
};
  
//C++容許多繼承
class D:public B,public C{
public:
    D(int a,int b,int c):B(a,b),C(a,c),A(a){
  
    }
     
};

 

 

1.繼承的調用順序

#pragma  once

#include <iostream>
using namespace std;

class F{

public:
    F(){ k5 = 10;  cout << "F:F()" << endl; }
    ~F(){ cout << "F:~F()" << endl; }
    //virtual ~F(){}

    void FuncA(){ cout << "F:FuncA()" << endl; }
    virtual void FuncB() { cout << "F::FuncB()" << endl; }
    int k5;

protected:
    int k4;

};

class Z : public  F{

public:
    Z(){ k5 = 5; cout << "Z:Z()" << endl; }
    ~Z(){ cout << "Z:~Z()" << endl; }
    

    void FuncA(){ cout << "Z::FuncA()" << endl; }
    void FuncB() { cout << "Z::FuncB()" << endl; }
    int k5;
    
protected:
    int k4;

};

 

#include "Jicheng.h"

int main()
{
    F* a = new F();  //F()
    cout << endl;

    F* a1 = new Z();  //F() Z()
    cout << endl;

    Z* a2 = new Z();  //F() Z()
    cout << endl;

    //Z* a3 = new F();  錯誤

    a->FuncA();  //F:FunA()
    a1->FuncA();  //F:FunA()
    a2->FuncA();  //Z:FunA()  若是子類沒有相應的函數,那麼會調用父類的函數

    a->FuncB();  //F:FunB()
    a1->FuncB();  //Z:FunB()
    a2->FuncB();  //Z:FunB()

    int k5 = a->k5;  //10
    int k4 = a1->k5;  //10
    int k3 = a2->k5;  //5

    //int k55 = a->k4;  k4是保護成員,沒法訪問

    delete a;  //~F()
    cout << endl;

    delete a1;  //若是父類析構函數加virtual 那麼會多一個子類的析構函數 ~Z()  ~F() 
    cout << endl;

    delete a2;  //~Z()  ~F()
    cout << endl;


    system("pause");

    return 0;
}

 

 

2.繼承的訪問權限

(1)類繼承訪問權限

父類的private成員沒法被繼承

(1)public繼承:父類的public/protected成員繼承到子類的訪問權限不變

(2)private繼承:父類的public/protected成員繼承到子類變爲private

(3)protected繼承:父類的public/protected成員繼承到子類變爲protected

 

(2)成員訪問權限

(1)private:①能被基類函數 ②能被友元函數 訪問,沒法被基類對象訪問

(2)protected:①能被基類函數 ②能被友元函數 ③能被子類函數 訪問,沒法被基類對象訪問

(3)public:①能被基類函數 ②能被友元函數 ③能被子類函數 ④能被基類對象

 

3.繼承的隱藏規則

隱藏是指派生類的函數屏蔽了與其同名的基類函數。注意只要同名函數,無論參數列表是否相同,基類函數都會被隱藏

 

四.多態

1.虛函數(覆蓋,Override)

覆蓋是指派生類函數覆蓋基類函數,特徵:(1)不一樣範圍,分別位於派生類和基類

                                                                     (2)函數名字相同

                                                                     (3)參數相同

                                                                     (4)基類函數必須有virtual關鍵字

 

主要是實現了多態的機制,簡而言之就是用父類(基類)的指針指向子類(派生類)的對象,而後經過父類(基類)的指針調用不一樣子類(派生類)的對象的不一樣函數,這就是一種泛型.

一個公有派生類對象能夠賦值給基類的對象,可是基類的對象不能賦值給派生類的對象

虛函數通常用於基類成員函數來綁定派生類成員函數一塊兒調用

默認狀況下成員函數不能動態綁定,可是添加virtual函數(虛函數)可讓函數有晚綁定的靈活性

 

2.虛函數的使用

//1.在基類用virtual聲明成員函數爲虛函數,
class Base{
  
    virtual void A();
};
  
//在類外定義虛函數無需加virtual
void Base::A(){
  
}
  
//2.在派生類從新定義虛函數,要求函數名/函數類型/函數參數的類型和個數保持一致
class Derive : pubic Base{
  
    //虛函數在派生類從新聲明時,無需加virtual
    void A();
};
  
//3.定義一個指向基類對象的指針變量,並使用基類對象的指針變量指向不一樣的派生類對象的函數
void main(){
    Base* p=new Derive();
    p->A();
}

 

class Base {
public:
    Base() {echo();}
    virtual void echo() {printf(「Base」);}
};
   
class Derived:public Base {
public:
    Derived() {echo();}
    virtual void echo() {printf(「Derived」);}
};
   
int main() {
    Base* base = new Derived();
    base->echo();  //輸出Base Derived  Derived
    return 0;
}

 

3.動態綁定技術

#include <iostream>
using namespace std;
class A
{
public:
    virtual void func(int val = 1)
    {
        std::cout " << val << std::endl;
    }
    virtual void test()
    {
        func();
    }
};
class B : public A
{
public:
    void func(int val = 0)
    {
        std::cout " << val << std::endl;
    }
};
int main(int argc, char* argv[])
{
    A*p1 = new A;
    A*p2 = new B;
    //B*p3 = new A;    //error
    B*p3 =  reinterpret_cast<B*> (new A);
    B*p4 = new B;
    //測試test()
    p1->test();    //A->1
    p2->test();    //B->1
    p3->test();    //A->1
    p4->test();    //B->1
    //測試func()
    p1->func();    //A->1
    p2->func();    //B->1
    p3->func();    //A->0
    p4->func();    //B->0
    return 0;
}

 

#include <iostream>
using namespace std;
class A
{
public:
    void func(int val = 1)
    {
        std::cout " << val << std::endl;
    }
    //這個test()的virtual無關緊要
    virtual void test()
    {
        func();
    }
};
class B : public A
{
public:
    void func(int val = 0)
    {
        std::cout " << val << std::endl;
    }
};
int main(int argc, char* argv[])
{
    A*p1 = new A;
    A*p2 = new B;
    //B*p3 = new A;    //error
    B*p3 = reinterpret_cast<B*> (new A);
    B*p4 = new B;
    //test()
    p1->test();    //A->1
    p2->test();    //A->1
    p3->test();    //A->1
    p4->test();    //A->1
                   //func()
    p1->func();    //A->1
    p2->func();    //A->1
    p3->func();    //B->0
    p4->func();    //B->0
    return 0;
}

 

4.虛析構函數

虛析構函數的做用是delete動態對象時釋放資源

//test.h
class A{
  
public:
    char* strA;
    A(char* a){
  
        strA=new char[12];
        strncpy(strA,a,strlen(a));
    }
    virtual  ~A(){  //不加virtual會報錯
        delete strA;
    }
};
  
class B:public A{
  
public:
    char* strB;
    B(char* a):A(a){
  
        strB=new char[12];
        strncpy(strB,a,strlen(a));
    }
    ~B(){
        delete strB;
    }
};
  
//test.cpp
int main(){
  
    char input[]="Hello";
    A* a=new B(input);
    delete[] a;
  
      
    system("pause");
  
    return 0;
}
相關文章
相關標籤/搜索