Q:對象中成員變量的初始值是多少?ios
#include <iostream> using namespace std; class Test { private: int i; int j; public: int getI() { return i; } int getJ() { return j; } }; int main() { Test t1; cout<<"t1.getI()="<<t1.getI()<<endl; cout<<"t1.getJ()="<<t1.getJ()<<endl; }
輸出的結果爲
markdown
#include <iostream> using namespace std; class Test { private: int i; int j; public: int getI() { return i; } int getJ() { return j; } }; Test gt; int main() { cout<<"gt.getI()="<<gt.getI()<<endl; cout<<"gt.getJ()="<<gt.getJ()<<endl; Test t1; cout<<"t1.getI()="<<t1.getI()<<endl; cout<<"t1.getJ()="<<t1.getJ()<<endl; Test* pt = new Test; cout<<"pt->getI()="<<pt->getI()<<endl; cout<<"pt->getJ()="<<pt->getJ()<<endl; delete pt; return 0; }
結果如圖
小結
從程序設計的角度,對象只是變量
1.在棧上建立對象時,成員變量初始爲隨機值
2.在堆上建立對象時,成員變量初始值爲隨機值
3.在靜態區建立對象時,成員變量初始值爲0值ide
解決方案:
1.在類中提供一個public的intialize函數
2.對象建立後當即調用intialize函數進行初始化
示例函數
#include <iostream> using namespace std; class Test { private: int i; int j; public: int getI() { return i; } int getJ() { return j; } void initialize() { i = 1; j = 2; } }; Test gt; int main() { gt.initialize(); cout<<"gt.getI()="<<gt.getI()<<endl; cout<<"gt.getJ()="<<gt.getJ()<<endl; Test t1; //t1.initialize(); cout<<"t1.getI()="<<t1.getI()<<endl; cout<<"t1.getJ()="<<t1.getJ()<<endl; t1.initialize(); Test* pt = new Test; pt->initialize(); cout<<"pt->getI()="<<pt->getI()<<endl; cout<<"pt->getJ()="<<pt->getJ()<<endl; delete pt; return 0; }
運行結果
Q:當intialize的位置出現了改變的話,還會對其進行初始化嗎
輸出結果如圖所示,發現intialize位置改變了以後,初始化也出現了問題
存在的問題
1.intialize只是一個普通函數,必須顯示調用
2.若是爲調用intialize函數,運行結果是不肯定的
解決方法
C++中能夠定義與類名相同的特殊成員函數--這種特殊的成員函數叫作構造函數
1.構造函數沒有任何返回類型的聲明
2.構造函數在對象定義時自動被調用spa
示例設計
#include <iostream> using namespace std; class Test { private: int i; int j; public: int getI() { return i; } int getJ() { return j; } Test() { printf("Test() Begin\n"); i = 1; j = 2; printf("Test() End\n"); } }; Test gt; int main() { cout<<"gt.getI()="<<gt.getI()<<endl; cout<<"gt.getJ()="<<gt.getJ()<<endl; Test t1; cout<<"t1.getI()="<<t1.getI()<<endl; cout<<"t1.getJ()="<<t1.getJ()<<endl; t1.initialize(); Test* pt = new Test; cout<<"pt->getI()="<<pt->getI()<<endl; cout<<"pt->getJ()="<<pt->getJ()<<endl; delete pt; return 0; }
運行結果
小結
1.每一個對象在使用以前都應該初始化
2.類的構造函數用於對象的初始化
3.構造函數與類同名而且沒有返回值
4.構造函數在對象定義時自動被調用code
帶有參數的構造函數
1.構造函數能夠根據須要定義參數
2.一個類中能夠存在多個重載的構造函數
3.構造函數的重載遵循C++重載的規則
對象定義和對象聲明不一樣
1.對象定義--申請對象的空間並調用構造函數
2.對象聲明--告訴編譯器存在這樣一個對象
示例對象
#include <iostream> using namespace std; class Test { public: Test() { cout<<"Test()"<<endl;; } Test(int v) { cout<<"Test(int v)="<<v<<endl; } }; int main() { Test t; // 調用 Test() Test t1(1); // 調用 Test(int v) Test t2 = 2; // 調用 Test(int v) int i(100); cout<<"i="<<i<<endl; return 0; }
結果
小結
1.構造函數能夠根據須要定義參數
2.構造函數之間能夠存在重載關係
3.構造函數遵循C++中重載函數的規則
4.對象定義時會觸發構造函數的調用
5.在一些狀況下能夠手動調用構造函數get
1.無參構造函數--沒有參數的構造函數,當類中沒有定義構造函數時,編譯器默認提供一個無參構造函數,而且其函數體爲空
2.拷貝構造函數--參數爲const class_name&的構造函數,當類中沒有定義拷貝構造函數時,編譯器默認提供一個拷貝構造函數,簡單的進行成員變量的值的複製編譯器
拷貝構造函數的意義
1.兼容C語言的初始化方式
2.初始化行爲可以符合預期的邏輯
3.淺拷貝--拷貝後的物理狀態相同
4.深拷貝--拷貝後的邏輯狀態相同
小結1.C++編譯器會默認提供構造函數2.無參構造函數用於定義對象的默認初始狀態‘3.拷貝構造函數在建立對象時拷貝對象的狀態4.對象的拷貝由淺拷貝和深拷貝兩種方式