根據網上資料整理,供學習交流使用。
一
構造方法用來初始化類的對象,與父類的其它成員不同,它不能被子類繼承(子類可以繼承父類所有的成員變量和成員方法,但不繼承父類的構造方法)。因此,在創建子類對象時,爲了初始化從父類繼承來的數據成員,系統需要調用其父類的構造方法。
如果沒有顯式的構造函數,編譯器會給一個默認的構造函數,並且該默認的構造函數僅僅在沒有顯式地聲明構造函數情況下創建。
構造原則如下:
1. 如果子類沒有定義構造方法,則調用父類的無參數的構造方法。
2. 如果子類定義了構造方法,不論是無參數還是帶參數,在創建子類的對象的時候,首先執行父類無參數的構造方法,然後執行自己的構造方法。
3. 在創建子類對象時候,如果子類的構造函數沒有顯示調用父類的構造函數,則會調用父類的默認無參構造函數。
4. 在創建子類對象時候,如果子類的構造函數沒有顯示調用父類的構造函數且父類自己提供了無參構造函數,則會調用父類自己的無參構造函數。
5. 在創建子類對象時候,如果子類的構造函數沒有顯示調用父類的構造函數且父類只定義了自己的有參構造函數,則會出錯(如果父類只有有參數的構造方法,則子類必須顯示調用此帶參構造方法)。
6. 如果子類調用父類帶參數的構造方法,需要用初始化父類成員對象的方式,比如:
#include <iostream.h>
class animal
{
public:
animal(int height, int weight)
{
cout<<"animal construct"<<endl;
}
…
};
class fish:public animal
{
public:
fish():animal(400,300)
{
cout<<"fish construct"<<endl;
}
…
};
void main()
{
fish fh;
}
在fish類的構造函數後,加一個冒號(:),然後加上父類的帶參數的構造函數。這樣,在子類的構造函數被調用時,系統就會去調用父類的帶參數的構造函數去構造對象。這種初始化方式,還常用來對類中的常量(const)成員進行初始化,如下面的代碼所示:
class point
{
public:
point():x(0),y(0)
private:
const int x;
const int y;
};
二 補充,類調用構造函數與析構函數
類指針的聲明,是不會調用構造函數的;但是指向一個類實例(new)就會調用構造函數。
但是類的聲明,會調用默認構造函數。
#include<iostream>
using namespace std;
class TestClass{
char x;
public:
TestClass() { cout << 'A'; }
TestClass(char c) { cout << c; }
~TestClass() { cout << 'B'; }
};
int main() {
TestClass p1, *p2;
p2 = new TestClass('X');
delete p2;
return 0;
}
TestClass p1, *p2; //只爲p1調用默認構造——A
p2 = new TestClass(‘X’); //調用構造函數,由p2指向——X
delete p2; //釋放內存空間,p2所指實例調用析構函數——B
return 0; //程序結束,p1調用析構——B