#includec.父類中被重寫的函數依然會繼承給子類,僅僅是被子類中的函數隱藏了。但是可以通過作用域分辨符:: 來訪問父類中被隱藏的函數using namespace std; class parent { public: void fun(int a) //這兩個函數發生了重載 { cout << "parent fun() " << a << endl; } void fun() { cout << "parent fun() " << endl; } }; class child : public parent { public: void fun() //與上面父類中的函數發生了重寫 { cout << "child fun() " << endl; } }; int main() { child c; c.parent::fun(4); //這裡發生了函數的重載 c.parent::fun(); c.fun(); //發生了函數的重寫 隱藏了父類中的同名函數 //c.fun(4); //這裡會報錯 因為沒有發生函數重載 被子類的函數隱藏了 return 0; }
#include注意:如果子類與父類存在同名成員,child c子類對象去訪問同名成員,訪問到的一定是子類中的同名成員,把父類繼承過來的同名成員隱藏(此時是子類的類型)。如果父類的指針或引用指向子類對象的時候,存在同名成員,通過指針或引用訪問到的一定是父類的同名成員,子類的同名成員不是被隱藏了,而是根本就沒有賦值過來(此時是父類的類型)。這裡就說明一個問題,變量的類型決定變量的行為!!!(但是前提一定是沒有設置虛函數)using namespace std; class parent { public: int a; int b; void fun() { cout << "parent fun " << endl; } }; class child : public parent { public: int a; void fun() { cout << "child fun " << endl; } }; int main() { child c; c.a = 10; c.b = 100; parent *p = &c; parent &p1 = c; cout << p->a << endl; cout << p1.a << endl; cout << p1.b << endl; cout << p->b << endl; p->fun(); p1.fun(); return 0; }
#include注意:對於虛函數的聲明,其實僅僅在父類中聲明就可以了,不用再在子類中進行聲明了。也可以即在父類中聲明,也在子類中聲明。using namespace std; class parent { public: virtual void fun() { cout << "parent fun() " << endl; } }; class child : public parent { public: virtual void fun() { cout << "child fun() " << endl; } }; int main() { child c; parent *p = &c; p->fun(); //同樣的語句 有不同的表現形式 parent d; p = &d; p->fun();//次條語句 具有多態的特性 return 0; }
#include注意:出於效率的考慮,沒有必要將所有成員函數都聲明為虛函數。通過虛函數表指針VPTR調用重寫函數是在程序運行時進行的,因此需要通過尋址操作才能確定真正應該調用的函數。而普通成員函數是在編譯時就確定了調用的函數。在效率上,虛函數的效率要低很多。 c.虛函數與多態的關系:多態是依靠虛函數實現的。但是就算我不想實現多態,依然可以在類中定義虛函數的,類創建對象時,依然產生虛函數表,依然存在VPTR指針。 d.對象在創建的時候由編譯器對VPTR指針進行初始化,只有當對象的構造完全結束後VPTR的指向才最終確定,父類對象的VPTR指向父類虛函數表,子類對象的VPTR指向子類虛函數表。 e.構造函數中調用虛函數無法實現多態:說明下這個知識點,是本節的一個疑問。如果有大神路過,希望大神指點下。也希望再日後的學習中,自己可以補充上來!!!對於唐老師的 構造函數與VPTR指針之間的關系分析(唐老師的白板圖)、還有那個this指針的舉例的觀點(唐老師的代碼),我有所保留!!!待日後提高!!!這裡面有一個不知對錯的反例,代碼如下:using namespace std; class parent { public: int a; virtual void fun() { cout << "parent fun()" < fun(); return 0; }
#include雖然不確定,但是依然記住構造函數中無法使用虛函數完成多態。using namespace std; class parent { public: parent() { cout << "hello parent()" << endl; } virtual void fun() { cout << "parent fun() " < fun(); } void fun() { cout << "child fun() " << endl; } }; int main() { parent p; child c(&p); child c1(&c); }
class shape { public: virtual double area() = 0; };注意:area為純虛函數,= 0 是告訴編譯器,這個函數是純虛函數,故意只聲明不定義函數體
#includeusing namespace std; class Shape { public: virtual double area() = 0; }; class Rectangle : public Shape { double m_a; double m_b; public: Rectangle(double a, double b) { m_a = a; m_b = b; } double area() { return m_a * m_b; } }; class Circle : public Shape { double m_r; public: Circle(double r) { m_r = r; } double area() { return 3.14 * m_r * m_r; } }; void area(Shape* s) { cout< area()<