程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 第15章 面向對象編程(12)

第15章 面向對象編程(12)

編輯:C++入門知識

15.5.3 作用域與成員函數
在基類和派生類中使用同一名字的成員函數,其行為與數據成員一樣:在派生類作用域中派生類成員將屏蔽基類成員。即使函數原型不同,基類成員也會被屏蔽。

class Base 

public: 
    int Get(){ 
        return 0; 
    } 
}; 
 
class Child:public Base 

public: 
    int Get(int i){ 
        return i; 
    } 
}; 

Child c=Child(); 
cout<<c.Get(10)<<endl; //Get(int) hide Base::Get() 
回憶一下,局部作用域中聲明的函數不會重載全局作用域中定義的函數,同樣,派生類中定義的函數也不重載基類中定義的成員。通過派生類對象調用函數時,實參必須與派生類中定義的版本相匹配,只有在派生類根本沒有定義該函數時,才考慮基類函數。
重載函數
像其他任意函數一樣,成員函數(無論虛還是非虛)也可以重載。派生類可以重定義所繼承的0個或多個版本。
如果派生類重定義了重載成員,則通過派生類型只能訪問派生類中重定義的那些成員。

class Base 

public: 
    int Get(){ 
        return 0; 
    } 
    double Get(double i){ 
        return i; 
    } 
}; 
 
class Child:public Base 

public: 
    using Base::Get;  
    int Get(int i){ 
        return i; 
    } 
}; 

Child c=Child(); 
cout<<c.Get()<<endl;     //0 
cout<<c.Get(10.2)<<endl; //10.2 
如果派生類想通過自身類型使用所有的重載版本,則派生類必須要麼重定義所有重載版本,要麼一個也不重定義。
派生類不用重定義所繼承的每一個基類版本,它可以為重載成員提供using聲明,一個using聲明只能指定一個名字,不能指定形參表。
15.5.4 虛函數與作用域
要獲得動態綁定,必須通過基類的引用或指針調用虛函數。

class Base 

public: 
    virtual int Get(){   //must be virtual func. 
        return 0; 
    } 
}; 
 
class Child:public Base 

public: 
    int Get(){ 
        return 1; 
    } 
}; 

Base c1=Child(); 
cout<<c1.Get()<<endl;     //0 
Base *c2=new Child(); 
cout<<c2->Get()<<endl;    //1 
通過基類調用被屏蔽的虛函數
通過基類類型的引用或指針調用函數時,編譯器將在基類中查找該函數而忽略派生類。
確定函數調用遵循以下四個步驟:
(1)首先確定進行函數調用的對象、引用或指針的靜態類型。
(2)在該類中查找函數,如果找不到,就在直接基類中查找,如此循著類的繼承鏈往上找,直到找到該函數或者查找完最後一個類。如果不能在類或者相關基類中找到該名字,則調用是錯誤的。
(3)一旦找到了該名字,就進行常規類型檢查,查看如果給定找到的定義,該函數調用是否合法。
(4)假定函數調用合法,編譯器就生成代碼。如果函數是虛函數且通過引用或指針調用,則編譯器生成代碼以確定根據對象的動態類型運行哪個版本函數,否則,編譯器生成代碼直接調用函數。

摘自 xufei96的專欄
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved