虛函數調用的幾種方式
/* * 虛函數的三種調用 * 1: 指針 * 2: 引用 * 3: 對象(不能實現多態) */ #include <iostream> //繼承,默認情況下class是私有繼承 struct默認是公有繼承 //虛函數可以調用成員函數 //多態調用依賴於指針 或 引用調用 //對象的調用有副本機制,會調用拷貝構造 拷貝一個父類 無法實現多態 //p->go(); //多態調用 //p->myclass::go(); //原生調用 //虛函數重載和返回值無關 和參數的類型 個數 順序有關 //虛函數被繼承下來了還是虛函數 //如果要使用被繼承的虛函數 不允許出現虛函數重載和覆蓋 //多態可以跨類 爺爺輩的指針 可以存儲孫子輩的地址 父輩拔針的地址 class myclass { public: int i; virtual void go() { i = 0; show(); } void show() { std::cout << "myclass->show()" << std::endl; } virtual ~myclass() { // 不加virtual 會造成內存泄漏 } }; class newmyclass: public myclass { public: void go() { std::cout << "newmyclass->go()" << std::endl; } void show() { std::cout << "newmyclass->show()" << std::endl; } void put() { std::cout << "newmyclass->put()" << std::endl; } }; // 1: 指針 void test1(myclass *p) { p->go(); } // 2: 引用 void test2(myclass &p) { p.go(); } // 3: 對象 void test3(myclass my) { my.go(); } int main() { myclass my; my.go(); // 正常調用父類的go函數 newmyclass newmy; newmy.go(); // 正常調用子類的go函數 myclass *pmy(nullptr); pmy->show(); // 空指針可以調用show操作 //pmy->go(); // 空指針無法調用go函數,因為myclass類,沒有實例化為對象,go函數內部操作了對象的內部變量,此時該內部變量並沒有構造出來 myclass *p = new newmyclass; p->go(); // 調用子類的go函數 p->myclass::go(); // 指定調用父類的go函數 std::cout << typeid(p).name() << std::endl; // p的類型為父類類型指針 class myclass * std::cout << typeid(*p).name() << std::endl; // *p的類型為子類類型 class newmyclass test1(p); // 調用子類的go函數 test1(&my); // 調用父類的go函數 test1(&newmy); // 調用子類的go函數 // 引用在語言內部用指針實現,引用是操作受限了的指針(僅容許取內容操作) test2(*p); // 調用子類的go函數 test2(my); // 調用父類的go函數 test2(newmy); // 調用子類的go函數 // 對象作為參數,會使用拷貝構造函數,形成對象的副本 test3(*p); // 調用父類的go函數 test3(my); // 調用父類的go函數 test3(newmy); // 調用父類的go函數 //std::cout << "mytest" << std::endl; system("pause"); return 0; }
運行結果: