1. 程式人生 > >C++建構函式、解構函式、虛擬函式

C++建構函式、解構函式、虛擬函式

建構函式

1.建立物件時會依次呼叫基類和子類的建構函式,各個建構函式負責對自己類中定義的成員的初始化工作。

2.如果使用者不宣告任何建構函式,編譯器將提供一個預設建構函式(default constructor),只要使用者定義了自己的建構函式,不論包不包括預設建構函式,編譯器都不再提供預設建構函式,因此如果你不希望以不含引數的方式構造該類物件,那麼可以給出你希望的建構函式而不給出自定義的預設建構函式,而如果你沒有這種要求而這樣做的話,那麼你如果用不含引數的方式構造該類物件則會得到一個編譯器錯誤,因為編譯器找不到合適的建構函式來完成這個動作。

3.有3個函式是編譯器會自動為你編寫的,它們是拷貝建構函式,賦值操作符和解構函式。拷貝建構函式和賦值操作符作用類似,前者用一個物件構造一個新物件,後者用一個物件給另一個物件賦值,兩者還是有所區別的。

編譯器提供的拷貝建構函式和賦值操作符都是執行的“淺拷貝”,即對於類中的所有資料成員來說:如果是使用者自定義型別,就呼叫該類的拷貝建構函式;如果是內建型別,則使用“複製所有bits”的方式實現拷貝,這種淺拷貝對於指標成員會有問題,因為它會造成兩個指標指向一個記憶體地址的情況,這顯然是不正確的,為了避免這種情況,就應該對那些有指標成員的類自定義提供拷貝建構函式和賦值操作符,在實現中動態分配新的記憶體,這就是所謂的“深拷貝”。

拷貝建構函式和賦值操作符的不同體現在這個地方:因為前者進行的是初始化,而後者進行的是賦值,而對於引用物件和const物件是不可以進行賦值的,因此C++不允許對含有引用物件和const物件的類呼叫賦值操作符,否則會給出一個編譯錯誤。

解構函式

與建構函式可以有多個版本不同,解構函式只有一個版本,因為它不需要任何引數。

銷燬物件的時候按照與建構函式正好相反的順序依次呼叫子類和基類的解構函式。一般情況下使用者不需要自定義解構函式,編譯器提供的建構函式就足夠了(其實它什麼都不做),因為除了動態分配的記憶體外,其餘資料成員都會在該物件生命週期結束時自動被銷燬。正如剛才所說,當物件中含有動態分配記憶體的資料成員時,就需要自定義解構函式來呼叫delete來釋放那些記憶體了。

對於基類來說,將解構函式定義為virtual是適合的,因為基類指標或引用可能被用來指向子類物件,而如果通過該指標或引用來呼叫delete來析構該物件的話,如果基類的解構函式不是virtual,那麼這種行為是c++沒有定義的,通常會呼叫基類的解構函式(而合適的做法顯然是呼叫子類,也就是該物件實際型別的解構函式),這樣的結果會是這個物件的基類部分被析構而子類部分沒有得到析構。

虛擬函式

C++使用虛擬函式機制來實現多型。一個函式從它被宣告為virtual的那一層基類起就永遠是virtual的,不管子類是否覆蓋它,也不管子類在覆蓋它的時候是否宣告為virtual。只有通過基類指標或者引用呼叫虛擬函式的時候才表現出多型(也就是執行時決定呼叫哪個函式),除此之外,如果用基類物件呼叫當然會呼叫基類函式,如果用子類指標、引用或物件呼叫都會呼叫子類函式(如果覆蓋了的話,如果沒覆蓋當然呼叫基類函式)。

C++通過vptr和vtbl來實現執行時多型。任何有至少一個virtual函式的類,其物件對比那些正常類的物件都多一個數據成員,就是vptr,這是一個指向vtbl的指標,而vtbl(虛擬函式表,包含該類所有虛擬函式對應的函式地址)只需要由整個類維護一個就好了。編譯器在編譯的時候對於有多型效應的函式呼叫(即由基類指標或引用呼叫的虛擬函式)用該函式在vtbl中的下標代替(猜測:基類的vtbl和子類vtbl的前半部分相同,這樣下標才能一致),然後在執行時動態構造物件時,可以根據該物件中的vptr找到正確的vtbl(即該物件真實類別對應的虛擬函式表),再根據下標找到正確的虛擬函式。


相關推薦

學習kotlin第13天_具體化的型別引數內聯屬性宣告集合

繼續之前的坑,我原本不打算繼續看文件了,直接上手個小專案,但是專案中遇見個小問題,list似乎和java中的有區別。。。一查文件發現在後面。。。所以繼續踩坑。 坑1、有時候我們需要型別作為引數傳給

C++筆記】編寫類string的建構函式函式和賦值函式

#include<iostream> using namespace std; class String { public: String(const char *str=NULL); //普通建構函式 String(const Stri

C++類中的一些細節(過載重寫覆蓋隱藏,建構函式函式拷貝建構函式賦值函式在繼承時的一些問題)

1 函式的過載、重寫(重定義)、函式覆蓋及隱藏 其實函式過載與函式重寫、函式覆蓋和函式隱藏不是一個層面上的概念。前者是同一個類內,或者同一個函式作用域內,同名不同引數列表的函式之間的關係。而後三者是基類和派生類函式不同情況下的關係。 1.1 函式過載

C++中class類 的 建構函式函式

說明: demo.cpp:main.cpp所在之處 Line.h:線段類的.h檔案 Line.cpp:線段類的.cpp檔案 Coordinate.h:座標類的.h檔案 Coordinate.cpp:

c++單鏈表【建構函式運算子過載函式增刪查改等】

c++中的單向連結串列寫法:實現增刪查改、建構函式、運算子過載、解構函式等。建立標頭檔案SList.h#pragma once typedef int DataType; //SList要訪問SListNode,可以通過友元函式實現,友元函式在被訪問的類中 class SL

C++在單繼承多繼承虛繼承時,建構函式複製建構函式賦值操作符函式的執行順序和執行內容

一、本文目的與說明     1. 本文目的:理清在各種繼承時,建構函式、複製建構函式、賦值操作符、解構函式的執行順序和執行內容。     2. 說明:雖然複製建構函式屬於建構函式的一種,有共同的地方,但是也具有一定的特殊性,所以在總結它的性質時將它單獨列出來了。  

C++ (建構函式函式動態申請空間)

#include<iostream> #include<string.h> using namespace std; //整型陣列: class IntArray//動態陣列 {

[c/c++]建構函式函式中可不可以丟擲異常

usingnamespace std;class A...{public:    A()    ...{        cout <<"construction fun"<< endl;        throw1;    }    ~A()    

C/C++面試題:編寫類String的建構函式函式和賦值函式

考點:建構函式、解構函式和賦值函式的編寫方法出現頻率:☆☆☆☆☆已知類String的原型為:        class String        {        public:                String(const char *str = NULL);

C++第十週【任務2】定義一個名為CPerson的類,有以下私有成員:姓名身份證號性別和年齡,成員函式建構函式函式輸出資訊的函式

/* (程式頭部註釋開始) * 程式的版權和版本宣告部分 * Copyright (c) 2011, 煙臺大學計算機學院學生 * All rights reserved. * 檔名稱: C++第十週【任務2】 * 作

C++ 建構函式預設建構函式函式和物件初始化

#include <iostream> using namespace std; class Student{     private:         int m_age;         int m_grade;         string m_sex

C++建構函式函式虛擬函式

建構函式 1.建立物件時會依次呼叫基類和子類的建構函式,各個建構函式負責對自己類中定義的成員的初始化工作。 2.如果使用者不宣告任何建構函式,編譯器將提供一個預設建構函式(default constructor),只要使用者定義了自己的建構函式,不論包不包括預設建構函式,編

C++中建構函式函式虛擬函式及普通成員函式的理解

這裡我們主要討論建構函式、解構函式、普通成員函式、虛擬函式,對這幾種函式說說自己的理解。 對建構函式的總結 對建構函式,我們先來看看如下的程式碼 #include <iostream> using namespace std; cla

關於c++預設的建構函式函式拷貝建構函式move函式

在c++中,當我們定義一個類的時候,如果我們什麼都不定義的時候,c++編譯器會預設的為我們生成一些函式。 例如定義一個Example類。 class Example{ }; 當我們定義一個Example類的時候,不定義任何操作的時候,c++編譯系統將為Example類生成如

c++編寫類String的建構函式函式和賦值函式

C++程式碼  按 Ctrl+C 複製程式碼 class String { public: String(const char *str = NULL);// 普通建構函式 String(const String &other);

找工作筆試面試那些事兒(5)---建構函式函式和賦值函式

作者:寒小陽 時間:2013年9月。 出處:http://blog.csdn.net/han_xiaoyang/article/details/10833931。 宣告:版權所有,轉載請註明出處,謝謝。 類的建構函式、解構函式與賦值函式     &

C++中抽象類以及虛/純虛函式的區別與介紹

一、虛擬函式 在某基類中宣告為 virtual 並在一個或多個派生類中被重新定義的成員函式,用法格式為:virtual+函式返回型別+ 函式名(引數表) {函式體};實現多型性,通過指向派生類的基類指標或引用,訪問派生類中同名覆蓋成員函式。 二、純虛擬函式 純虛擬函式是一種

請為CMyString型別編寫建構函式copy建構函式函式和賦值運算子函式

如下為型別CMyString的宣告,請為該型別編寫建構函式、copy建構函式、解構函式和賦值運算子函式。 1 class CMyString 2 { 3 public: 4 CMyString(const char* pData = nullptr); 5 CMyS

類和物件——建構函式函式複製建構函式

類: 要宣告類,用class,注意區分大小寫。類含有成員屬性和方法。在宣告類的末尾要加分號; 物件: 宣告完類之後,它並不能對程式產生任何影響。只有依據類,例項化物件,才可以訪問類成員屬性和方法。 下面是類例項化物件、動態分配記憶體與變數的對比: double pi=3.14; int* p

類的建構函式函式拷貝建構函式賦值函式

 類的四種基本預設函式:建構函式、解構函式、拷貝建構函式、賦值函式。 建構函式:建立類時,系統自動呼叫建構函式,用以初始化,分配空間,沒有自定義的建構函式時,系統預設一個無引數的建構函式。 class book { private:     int isBook;