1. 程式人生 > >C++基礎---靜態聯編與動態聯編

C++基礎---靜態聯編與動態聯編

1. 靜態聯編與動態聯編

1.1 函式聯編的定義

  • 函式聯編:將一個呼叫函式者聯結上正確的被呼叫函式的過程,一般稱為聯編。
  • C++中的聯編分兩種:
    (1)靜態聯編;
    (2)動態聯編;

1.2 靜態聯編的定義

  • 成員函式必須宣告為非virtual,即為非虛擬函式,該函式是靜態聯編
  • 靜態聯編:聯編工作出現在編譯連線階段,這種聯編又稱為早期聯編;
  • 編譯程式:在編譯階段,被調函式和呼叫函式的關係以及它們的記憶體地址在編譯時都已經確定好,執行時不再發生變化
    注:這樣的好處是速度快,因為執行時候不用對各個物件的函式進行跟蹤,只需要傳遞引數,執行確定好的函式並在函式呼叫完畢後清理記憶體即可。

1.3 在編譯時的靜態聯編

  • 在編譯時所進行的靜態聯編又稱為靜態約束。
  • 在編譯時就處理好了程式中的操作呼叫與執行該操作程式碼間的關係,可行
  • 程式碼示例:

    
    #include <iostream>
    
    using namespace std;
    class father
    {
    public:
        father(){}
        ~father(){}
    public:
        void run() const{cout<<"父親可以跑萬米"<<endl;}
    };
    class son : public father
    {
    public:
        son(){}
        ~son(){}
    public
    : void run() const{cout<<"兒子親可以跑十萬米"<<endl;} }; int main() { father f; f.run(); son s; s.run(); system("pause"); return 0; } =>父親可以跑萬米 兒子親可以跑十萬米

1.4 在執行時的靜態聯編

  • 用指標在執行時動態地指向某個物件,然後再用該物件呼叫它的成員函式。
  • 由於靜態聯編的物件與指標的關係在編譯時就已確定,因此執行時再對它改變也是無效的,不可行
  • 程式碼示例:

    
    #include <iostream>
    using namespace std; class father { public: father(){} ~father(){} public: void run() const{cout<<"父親可以跑萬米"<<endl;} }; class son : public father { public: son(){} ~son(){} public: void run() const{cout<<"兒子親可以跑十萬米"<<endl;} }; int main() { int choice = 0; while(1) { cout<<"(1)father(2)son(3)quit:"; father *p; bool quit = false; cin>>choice; switch(choice) { case 1: { p = new father; break; } case 2: { p = new son; break; } case 3: { quit = true; break; } default: { cout<<"請輸入1~3之間的整數"<<endl; } } if(true == quit) { break; } p->run(); } system("pause"); return 0; } =>(1)father(2)son(3)quit:1 父親可以跑萬米 (1)father(2)son(3)quit:2 父親可以跑萬米 (1)father(2)son(3)quit:3

1.5 動態聯編的定義

  • 成員函式必須宣告為virtual,即為虛擬函式,該函式是動態聯編
  • 動態聯編:聯編工作出現在執行時階段,這種聯編又稱為晚期聯編;
  • 編譯程式:在編譯階段並不能確切知道將要呼叫的函式,只有在程式執行時才能確定將要呼叫的函式,為此要確切知道該呼叫的函式,要求聯編工作要在程式執行時進行;
    注:這樣的好處是實現多型性和比較靈活,但是就要犧牲速度,因為每個函式呼叫在執行前是不可確定的,要隨著使用者的操作來執行相應的函式,相應地大大增加了系統的開銷。

1.6 在編譯時的動態聯編

  • 呼叫虛擬函式時,沒有采用指標或引用,通過類物件呼叫虛擬函式,那麼就無法實現動態聯編,不可行
  • 程式碼示例:

    
    #include <iostream>
    
    using namespace std;
    class father
    {
    public:
        father(){}
        ~father(){}
    public:
        virtual void run() const{cout<<"父親可以跑萬米"<<endl;}
    };
    class son : public father
    {
    public:
        son(){}
        virtual ~son(){}
    public:
        void run() const{cout<<"兒子親可以跑十萬米"<<endl;}
    };
    int main()
    {
        father f;
        son s;
        f.run();
        f = s;
        f.run();
        system("pause");
        return 0;
    }
    =>父親可以跑萬米
      父親可以跑萬米

1.7 在執行時的動態聯編

  • 呼叫虛擬函式時,只有在使用指標或引用時,才能實現在執行時的動態聯編,可行
  • 程式碼示例:

    
    #include <iostream>
    
    using namespace std;
    class father
    {
    public:
        father(){}
        ~father(){}
    public:
        virtual void run() const{cout<<"父親可以跑萬米"<<endl;}
    };
    class son : public father
    {
    public:
        son(){}
        virtual ~son(){}
    public:
        void run() const{cout<<"兒子親可以跑十萬米"<<endl;}
    };
    int main()
    {
        father *f=new father;
        f->run();
        son s;
        father *p = &s;
        p->run();
        system("pause");
        return 0;
    }
    =>父親可以跑萬米
      兒子親可以跑十萬米

參考文獻:
[1]《C++全方位學習》範磊——第十三章
[2]《C++程式設計教程(第二版)》錢能——第五章、第六章、第七章
[3]《C++ Primer(第5版)》王剛 楊巨峰——第一章、第六章
[4] 百度搜索關鍵字:C++函式聯編、虛擬函式、非虛擬函式、靜態聯編、編譯時靜態聯編、執行時靜態聯編、動態聯編、編譯時動態聯編、執行時動態聯編