C++:繼承和多態

虛函數:只有類的成員函數才能定義為虛函數

虛函數 在類的成員函數前面加上一個 virtual 關鍵字, 此時這個成員函數就叫做虛函數
虛函數 當在子類中定義了一個與父類完全相同的虛函數的時候,此時就叫做子類的虛函數重寫了父類的虛函數
構成多態的條件 派生類重寫基類的虛函數實現多態, 必須要求函數名相同參數列表以及返回值相同(協變除外)
協變 派生類重寫基類的虛函數的時候函數名相同, 參數列表相同, 但是返回值可以不同(返回值是父子關系)

靜態成員函數不能定義為虛函數

靜態成員函數是屬于這個類的, 它不屬于某個對象, 而虛函數必須有一張虛表, 但是虛表存在于對象中,靜態成員函數既然不屬于對象,那么何來的虛表呢, 沒有虛表又何談虛函數呢
類外定義虛函數 只能在聲明虛函數的時候在虛函數前面加上一個 virtual 關鍵字, 當在類外定義的時候, 此時就不能在其前面加上 virtual 關鍵字

構造函數 構造函數不能為虛函數.

原因是虛函數必須有一張虛表, 但是虛表又存在于對象中, 那么問題來了, 構造函數是為了構造出對象的, 現在對象都沒有, 拿來的虛表, 沒有虛表拿來的虛函數

父類是虛函數,子類會繼續保持,反之不成立

不要在析構函數或者構造函數中調用虛函數

因為在構造函數和析構函數中對象會不完整, 而虛函數的前提是存在于虛表中, 虛表又存在于對象中, 對象不完整,如何找到虛函數呢

最好把基類的析構函數聲明為虛函數

class Person
{...
};class Student:public Person
{...
};int main()
{Person* p = new Student;delete p;return 0;
}

看到上面的場景中, 我們第一反應就是當我們一次New, 一次delete沒有任何問題, 但是問題來了, 如果Student中除了普通成員函數外, Student 對象在析構的時候還需要我們自己去清理, 此時delete的只是父類的對象, 那student中需要清理的內存沒有得到清理,此時不就造成內存泄露了嗎?
同時注意, 子類和父類的析構函數在編譯的時候編譯器會將兩者處理為相同函數名, 因此當定義為虛函數的時候,此時關注的就是對象了, 在釋放的時候會看一下p是一個student的對象,因此會清理student中的東西,此時就不會造成內存泄露了
將析構函數定義為虛函數的目的就是為了在析構的時候當對象是子類的時候清理子類,當對象是父類的時候清理父類,已達到資源正確釋放

多態:虛函數指針或引用+父類指針或引用

多態條件
當使用基類指針或者引用調用重寫的虛函數的時候,此時指向父類調用的就是父類的虛函數,指向子類調用的就是子類的虛函數

為什么指針和引用可以實現多態而對象不能實現多態

class A
{
public:virtual void Debug(){}
};class B:public A
{
public:virtual void Debug(){}
};void main()
{B b;A a = b;A * point_A = &b;a.Debug();point_A->Debug();
}

——對于程序A a = b而言,b內存布局在賦值的時候已經從B轉換到A了,多于的數據都被丟棄,因此其就是一個A類型變量,那么a.Debug這里的a就是一個A類型的變量。
——對于point_A來說,它是一個指針,其類型雖然是A,但指向的區域的內容卻是一個B類型的內存結構,雖然內存結果的布局與A兼容,但其虛函數表中的Debug卻是B的實現。

內聯函數不能定義為虛函數

虛函數必須有虛表,虛表中存放的是地址,但是內聯在編譯的過程中會被展開,它沒有地址何來的虛表,沒有虛表何來的虛函數

調用普通函數比調用虛函數快

因為普通函數就是直接call到一個地址,而調用虛函數得先找到虛表, 然后拿著虛表中的地址再找到虛函數, 因此虛函數是間接尋址, 多了訪存次數, 當然也就比普通函數慢了

重寫重載重定義的區別

重載 重載函數必須在同一作用域內,滿足函數名相同, 參數不同的函數就叫做函數之間構成了重載
重寫(覆蓋)不同作用域內(基類和派生類)函數名相同, 參數相同, 返回值相同(協變除外), 同時函數前必須有 virtual 修飾
重定義(隱藏) 不同作用域內(基類和派生類)函數名相同, 只要不是重寫就是重定義

繼承與靜態函數

基類中定義了static成員, 則整個繼承體系中只有一個static成員, 無論派生出多少個子類, 都只有一個static成員實例

純虛函數

成員函數形參后面加上 = 0, 此時的成員函數就會變成純虛函數. 同時包含純虛函數的類就叫做抽象類(接口類)
純虛函數只有在派生類中重新定義后才能實例化出對象
抽象類不能實例化出對象

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/383900.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/383900.shtml
英文地址,請注明出處:http://en.pswp.cn/news/383900.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

POJ 1061擴展歐幾里得

擴展歐幾里得的模板題&#xff0c;需要注意的是為了得到一個最小正數解我們要使axbyc中的a,b都是正數 #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<iostream> #include<cmath> #include<ctim…

C++::探索對象模型

前面我們已經知道, 在沒有虛函數的時候, 對象的大小就是對應的成員變量的大小, 而成員函數不會占用對象的空間, 今天我們來討論一下, 當類中定義了虛函數的時候, 此時對象的大小以及對象模型 非繼承下的對象模型 class Base { public:virtual void func1(){cout << &qu…

auto_ptr

#include <iostream> #include <memory> using namespace std;class A { public:A(){cout<<"構造"<<endl;}~A(){cout<<"A析構"<<endl;}void fun(){cout<<"A::fun"<<endl;} };class PA { public…

POJ 2142——擴展歐幾里得

題目是很裸的擴展歐幾里得&#xff0c;但是對x,y有限制條件&#xff0c;要求所有x,y中abs(x)abs(y)最小&#xff0c;在這個條件下要求abs(a* x)abs(b* y)最小 顯然我們需要用擴展歐幾里得求得一組解&#xff0c;問題在于如何處理這組解以得到符合條件的值。 我是這樣處理的&a…

C++::模板

模板的簡單介紹 C中模板是為了能夠使得函數或者類實現范型編程的目的, 同時C模板的出現是為了避免代碼的冗余 舉個例子 void Swap(int& a, int& b) {int tmp a;b a;a b; } void Swap(char& a, char& b) {char tmp a;b a;a b; } 上面的函數除了類型不…

Linux select TCP并發服務器與客戶端編程

http://blog.csdn.net/szkbsgy/article/details/10558881 [cpp] view plaincopy <span style"font-size:18px;">服務端&#xff1a; #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/time.h> #i…

BZOJ - 2186 歐拉函數

題目的意思大概是求1~N!中和M&#xff01;互質的數的個數 因為對歐拉函數理解不夠深刻所以我是分析得到結果的&#xff1a; 當N<M的時候顯然符合要求的數的個數為0&#xff1b; 當N>M的時候我們要求的是1~N!中不含1 ~M的素因子的的數的個數&#xff0c;結合歐拉函數的…

多態相關概念

多態相關注意事項 所謂的多態就是指函數有多中狀態, 在C中通常是通過父類指針指向子類對象的方法實現多態, 這樣父類可以通過子類的類型調用不同的方法. 即實現一個接口多種方法, 多態的引用是為了實現接口復用 在 C中多態是通過虛函數來實現的. 子類通過對父類相關接口進行重…

模板實現棧隊列以及鏈表

模板實現鏈表 //test.h #include <iostream> #include <cstdio> #include <assert.h> using namespace std;template <class T> struct ListNode {ListNode* _prev;ListNode* _next;T _data;ListNode(const T& x):_prev(NULL),_next(NULL),_data(…

基于Visual C++2013拆解世界五百強面試題--題5-自己實現strstr

http://blog.csdn.net/itcastcpp/article/details/12907371 請用C語言實現字符串的查找函數strstr&#xff0c; 找到則返回子字符串的地址&#xff0c;沒有找到返回為空&#xff0c;請用數組操作與指針操作實現 看到題目想到最簡單的方法就是母字符串和子字符串比較&#xff0c…

卡特蘭數

卡特蘭數的引入與n邊形分成三角形的個數有關&#xff1a; 我們令f[n]表示n邊形可以分成的三角形的個數&#xff0c;特殊的&#xff0c;令f[2]1 我們考慮以頂點1頂點的一個三角形&#xff0c;假設用的是n邊形的k-k1邊&#xff0c;那么這種情況的方案數就是f[k]?f[n?k1]f[k]*…

軟件測試相關概念

什么叫軟件測試 軟件測試就是測試產品沒有錯誤,同時又證明軟件是可以正確運行的 測試和調試的區別 調試一般都在開發期間 ,測試是伴隨著整個軟件的生命周期, 調試是發現程序中問題并且解決問題, 測試是發現程序中的缺陷 軟件測試的目的和原則 目的:驗證軟件有沒有問題 原…

Linux 線程信號量同步

https://www.cnblogs.com/jiqingwu/p/linux_semaphore_example.html 信號量和互斥鎖(mutex)的區別&#xff1a;互斥鎖只允許一個線程進入臨界區&#xff0c;而信號量允許多個線程同時進入臨界區。 不多做解釋&#xff0c;要使用信號量同步&#xff0c;需要包含頭文件semaphore.…

本原勾股數組

勾股數我們都很熟悉&#xff0c;a2b2c2&#xff0c;可是如何快速找到所有的勾股數組呢&#xff1f; 本原勾股數組a2b2c2性質&#xff1a; 1. a,b奇偶不同&#xff0c;c一定是奇數 2. 若b為偶數&#xff0c;c-b和cb一定是完全平方數 3. 設t>s>1,且均為奇數&#xff0c;則…

C++靜態成員函數訪問非靜態成員的幾種方法

https://www.cnblogs.com/rickyk/p/4238380.html 大家都知道C中類的成員函數默認都提供了this指針&#xff0c;在非靜態成員函數中當你調用函數的時候&#xff0c;編譯器都會“自動”幫你把這個this指針加到函數形參里去。當然在C靈活性下面&#xff0c;類還具備了靜態成員和靜…

費馬大定理

當n>3時方程 xnynzn沒有正整數解 結論很簡潔&#xff0c;剛才看了一下證明的歷史&#xff0c;我勒個去。。。。

類中的靜態成員函數訪問非靜態成員變量

http://blog.csdn.net/u011857683/article/details/52294353 1.思路&#xff1a; 靜態成員函數屬于類(通過類訪問&#xff0c;調用函數時沒有提供this指針)&#xff0c; 非靜態成員函數屬于實例&#xff08;通過對象訪問&#xff09;&#xff08;默認都提供了this指針&#xf…

Pollar Rho算法

原本是想把這個算法搞懂的&#xff0c;然后在網上看了又看&#xff0c;覺得&#xff0c;還是有時間再來看吧&#xff0c;我錯了。 看到了一個大佬的博客&#xff0c;順帶收集一下板子 這個板子可以求大數的最大的因子。 #define LL long long bool IsPrime(LL);//返回素性測…

小知識點總結

用戶輸入一個url之后到整個頁面返回給客戶這個過程都經歷了一些什么 首先url是為了讓人記憶方便的,計算機在進行網絡傳輸的過程中只能通過ip地址找到對應的主機,所以當輸入一個ip地址的時候,此時就需要找對應的url,首先從瀏覽器中取查找ip地址,再到系統中去查找,再到域名解析服…

C++學習之普通函數指針與成員函數指針

http://blog.csdn.net/lisonglisonglisong/article/details/38353863 函數指針&#xff08;function pointer&#xff09;是通過指向函數的指針間接調用函數。相信很多人對指向一般函數的函數指針使用的比較多&#xff0c;而對指向類成員函數的函數指針則比較陌生。我最近也被問…