1. 程式人生 > >關於c++多型的測試(帶詳細註釋)

關於c++多型的測試(帶詳細註釋)

#include <iostream> #include <string> using namespace std; class Base{ public:     int a;     static int b;//在類中宣告的static變數必須在類外部再定義一次!,否則無法被呼叫.在類內不能初始化static成員(除了const成員),只能在類外     Base()     {         abc te;         a = 15;         te.i = 10;     }     class abc{     public:         int i;     };     //函式不能同時為virtual和static     virtual void test(){ cout << "this is parent test" << endl; }//基類一旦宣告為虛擬函式,且子類對此函式均為重寫     //當用基類物件訪問此函式時,會轉到子類定義的函式中.     void test1(){ cout << "this is parent test1" << endl; }     virtual int glh() = 0;//純虛擬函式必須在子類中實現     //static函式是全域性類的函式,由於函式不能同時為virtual和static,所以static函式不能被重寫     static void read() { cout << "this is parent read,value is " << b++ << endl; }//static函式在類內部或外部定義均可

}; int Base::b = 88;//必須在類外再次定義,並可以初始化 //void Base::read(){ cout << "this is parent read,value is " << b << endl; }//static函式只能訪問static成員變數 class Derived :public Base{ public:     Derived()     {         a = 19;     }     virtual void test(){//這裡不管加不加virtual,base->test();都會執行到這裡,但是引數型別和數量和返回型別必須與基類的函式相同,否則相當於重新定義了一個函式         cout << "this is Derived son test" << endl;}//如果註釋掉此函式,則基類指標會呼叫基類的base->test();     void test(string &str){ cout << "this is Derived son test,value is " << str << endl; }//此函式不能被基類直接訪問到     void test1(){ cout << "this is Derived son test1" << endl; }//此函式不能被基類直接訪問到,如果註釋掉此函式,那麼sobase.test1();     //會被報錯,因為子類定義的同名函式void test1(string &str)(不管引數相不相同,只要函式名相同,子類即覆蓋了繼承自基類對應的函式),如果想     //訪問基類的test1,一.將void test1(string &str)註釋掉,防止覆蓋;二.     void test1(string &str){ cout << "this is Derived son test1,value is " << str << endl; }//此函式不能被基類直接訪問到     static void read(){ cout << "this is son read,value is " << b++ << endl; }//在子類可以過載基類static函式,但同樣無法使用基類指標訪問     void write(){ cout << "this is son write" << endl;}     int glh(){ a = 3; return 1; } }; //總結:如果子類想通過基類指標訪問自己定義的函式,那麼需要將基類的對應函式宣告稱virtual重寫此函式,但是此指標是無法訪問子類其餘的過載函式,如 //Derived的test1(),只能通過子類的物件進行訪問. //為什麼要把子類的指標賦值給父類?如Base *base = &sobase; //我個人估計一年或者幾年之後你又會問“如何隱藏類的定義,讓使用者看不到類的實現細節”或者“如何讓使用者無法修改類的私有成員”。 //一個辦法就是用子型別多型。 //在父類定義所有需要用到的介面(公共成員函式)和允許使用者看到的資料,把父類暴露給使用者。而在子類中定義實現細節,使用者不知道子類的定義——甚至 //不知道子類叫什麼名字,將來哪怕完全替換掉子類的實現,換成另一個子類,使用者也會一無所知。最後需要做的就是寫一個函式來返回“子類指標”了 //——因為我們不想讓使用者知道子類的任何資訊,所以函式不能不能直接宣告成返回子類物件或者返回“子類指標”,正確的做法是宣告成返回父類指標, //而實際上,卻是把子類指標轉換成父類指標然後返回.這就是virtual的用處了. int main() {     int n;     string str("python");     Derived sobase;     Base *base = &sobase;     cout << base->a << endl;//19     base->test();//this is Derived son test     base->test1();//this is parent test1,同下     base->read();//b == 88     //base->test1(str);//如果在子類中過載基類的函式,那麼使用基類的指標是無法訪問此過載函式的,編譯器報錯     sobase.test1();//如果想訪問子類過載基類的函式,必須用子類的物件去訪問     sobase.test1(str);//如果想訪問子類過載基類的函式,必須用子類的物件去訪問     sobase.read();//b == 89     Derived ssbase;     ssbase.read();//b == 90,可以看出b是全域性的,不隨物件的變化而變化

    return 0; }