C++如何在構造函數和析構函數中調用虛擬函數
C++構造函數和析構函數中調用虛擬函數
C++構造器可以為虛擬函數嗎?
不行。
因為構造器調用的時候會設置當前類的虛表地址,然后如果構造函數本身為虛擬函數,那么調用構造函數就需要提前訪問虛表,此時虛表指針還沒有指向虛表,就沒法訪問虛表。
構造函數中可以調用虛擬函數嗎?
可以。
但是調用虛擬函數就是調用跟調用普通函數效果一樣。
因為子類在創(chuàng)建的時候是先調用父類的構造器,父類的構造器先設置好父類的虛表地址,然后再執(zhí)行構造器中的代碼,然后在回到子類構造器,先將虛表地址替換為子類的虛表地址,然后執(zhí)行子類構造器的代碼。
因此如果在父類構造器中調用虛函數,那么此時是從父類的虛表中查找函數地址,查找到的還是父類的虛函數地址。因此會調用父類的虛函數,而不會調用子類的虛函數。
析構函數中可以調用虛擬函數嗎?
可以。
但是調用虛擬函數跟調用普通函數沒啥區(qū)別。
因為析構的時候先執(zhí)行子類的析構函數,再執(zhí)行父類的析構函數,在執(zhí)行當前類的析構函數的時候會先將虛表地址設置為當前類的虛表地址,然后再從虛表里查找函數地址,因此找到的只能是當前的虛函數的地址。
父類的析構函數為什么要為虛函數?
因為如果父類析構函數不為虛函數,那么當對象析構的時候只會調用指針當前類型的析構函數,不會調用父類或者子類的析構函數,會導致資源泄漏。
如果父類的析構函數為虛函數,那么子類的析構函數在析構的時候會先調用子類的析構函數,再調用父類的析構函數。這樣子就不會存在資源泄漏。
注:
(1)將子類和父類構造器和析構器調用串起來是編譯器實現(xiàn)的
(2)子類和父類都有自己的虛表。子類或者父類的構造器和析構器在最開始都是將虛表設置為當前類的虛表。然后才真正調用構造函數和析構函數里的代碼。
C++構造函數和析構函數的調用順序
1、構造函數的調用順序
基類構造函數、對象成員構造函數、派生類本身的構造函數
2、析構函數的調用順序
派生類本身的析構函數、對象成員析構函數、基類析構函數(與構造順序正好相反)
3、特例
- 局部對象,在退出程序塊時析構
- 靜態(tài)對象,在定義所在文件結束時析構
- 全局對象,在程序結束時析構
- 繼承對象,先析構派生類,再析構父類
- 對象成員,先析構類對象,再析構對象成員
#include "stdafx.h"
#include <iostream>
using namespace std;
class ?Clock
{
public:
?? ?Clock()
?? ?{
?? ??? ?cout << "clock的構造函數" << ",";
?? ?}
?? ?~Clock()
?? ?{
?? ??? ?cout << "clock的析構函數" << ",";
?? ?}
};
class Date
{
public:
?? ?Date()
?? ?{
?? ??? ?cout << "date的構造函數" << ",";
?? ?}
?? ?~Date()
?? ?{
?? ??? ?cout << "date的析構函數" << ",";
?? ?}
};
void main()
{
? ? Clock c;
?? ?Date d;
?? ?system("pause");
}在使用構造函數和析構函數時,需要特別注意對它們的調用時間和調用順序。
在一般情況下,調用析構函數的次序正好與調用構造函數的次序相反:最先被調用的構造函數,其對應的(同一對象中的)析構函數最后被調用,而最后被調用的構造函數,其對應的析構函數最先被調用。
可以簡記為:先構造的后析構,后構造的先析構,它相當于一個棧,先進后出
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
C++中set/multiset與map/multimap的使用詳解
這篇文章主要為大家詳細介紹了C++中set/multiset與map/multimap的使用,文中的示例代碼講解詳細,具有一定的借鑒價值,需要的可以參考一下2023-02-02
Qt GUI圖形圖像開發(fā)之QT表格控件QTableView詳細使用方法與實例
這篇文章主要介紹了Qt GUI圖形圖像開發(fā)之QT表格控件QTableView詳細使用方法與實例,需要的朋友可以參考下2020-03-03

