1、編譯器會為類產生預設的建構函式、複製建構函式、賦值函數、解構函式,當然預設的這些函數,只是簡單的將對象的成員進行賦值。
2、如果類中的成員對象包含有需要通過new動態分配記憶體的成員,則需要重新定義複製建構函式、重載賦值操作符、解構函式、帶參數的建構函式,預設的建構函式。
3、衍生類別構造時,會先調用基類的建構函式(根據衍生類別的建構函式類型,調用基類對應形式的建構函式),接著調用衍生類別型的建構函式。
4、當類的生命週期結束時,會先調用衍生類別的解構函式、接著調用基類的解構函式。
5、建構函式和解構函式不能被繼承,各自處理各自成員賦值與析構。
6、深入理解對象生命的開始、結束,以及對象在記憶體中的位置(是在棧上、堆上?)、對象成員的記憶體布局,是理解上面四點的關鍵,防止記憶體流失的關鍵。
下面的代碼對以上6點進行實驗,細細琢磨.基類檔案people.h、people.cpp,衍生類別檔案woman.h、woman.cpp,主函數檔案testmain.cpp
#ifndef PEOPLE_H#define PEOPLE_Hclass people{private: char *name;public:people(); //預設的建構函式 people(const char *s); //帶參數的建構函式people(const people& p);//複製建構函式people & operator=(const people& p); //賦值函數 ~people();};#endif
#include "people.h"#include <stdio.h>#include <string.h>people::people() //預設的建構函式{printf("調用了預設的建構函式people()\n");name = new char[strlen("hello")+1]; //分配在堆上strcpy(name,"hello");}people::people(const char *s) //帶參數的建構函式{printf("調用了有參建構函式people(const char* s)\n");name = new char[strlen(s)+1]; strcpy(name,s);}people::people(const people & p){printf("調用了複製建構函式people(const people &p\n");name = new char[strlen(p.name)+1];strcpy(name,p.name);}people & people::operator=(const people &p){printf("調用了賦值函數operator=\n");if(this == &p)return *this;else{delete name;name = new char[strlen(p.name)+1];strcpy(name,p.name);return *this;}}people::~people(){printf("解構函式被調用~people()\n");delete name;}
#ifndef WOMAN_H#define WOMAN_H#include "people.h"class woman : public people{private:char *company; //增加一個指標成員,new分配記憶體,重新修改建構函式和解構函式int age;public:woman();//預設建構函式woman(const char * c,int a,const char * s); //有參數建構函式woman(const woman & w); //複製建構函式woman & operator=(const woman &w); //重載賦值操作符~woman();};#endif
#include "woman.h"#include <stdio.h>#include <string.h>woman::woman(){printf("調用了預設的建構函式woman()\n");char *s = "world";company = new char[strlen(s)+1];strcpy(company,s);age = 99;}woman::woman( const char * c,int a,const char * s):people(s) {printf("調用了有參數的建構函式woman( const char * s,int a)\n");company = new char[strlen(c)+1];strcpy(company,c);age = a;}woman::woman(const woman &w):people(w) //衍生類別的複製建構函式定義,由於衍生類別只能訪問自己的私人成員,因此需調用基類的複製建構函式people(const people & p){ //注意基類的複製建構函式的參數類型為people,而這裡傳遞的是衍生類別類型woman,基類會使用衍生類別型中的基類部分來構造基類對象 printf("調用了複製建構函式woman(const woman &w)\n"); company = new char[strlen(w.company)+1]; strcpy(company,w.company); age = w.age;}woman & woman::operator=(const woman & w) //這不是建構函式,因此不能夠通過直接調用基類的建構函式來實現衍生類別對象中基類成員賦值{ printf("調用了賦值函數woman::operator=(const woman & w)\n"); if (this == &w) return *this; //自己給自己賦值 else { delete company; //刪除原來佔用的記憶體空間 people::operator=(w); //調用基類的賦值操作,完成衍生類別對象中的基類對象的賦值,方式比較奇怪,先記住 company = new char[strlen(w.company)+1]; strcpy(company,w.company); return *this; } }woman::~woman(){ printf("調用了解構函式~woman()\n"); delete company;}