談談c++的初始化工作(3) (轉)
我們還是先來看看上次遺留的問題。“為什麼(上次異常是三個,這次是六個,可以解釋嗎)?怎麼辦?”這其中的原因,我想您是明白的,我只做簡單的重複:)。程式碼段中:
//bool IsSameMan(Human one,Human another)
if(IsSameMan(lucy,lily))//(1)
{
std::cout< }else
std::cout<
}
(1)句傳入兩個(lucy,lily),根據Human類的定義,試圖把它們的資源分別複製給one和 another,但毫無疑問出現了淺複製的問題。當區域性物件one和another析構時,問題表現出來了。至於為什麼是六個異常,呵呵,還是您來回答吧?
知道原因,就容易解決。我們需要一個複製構造,來完成這項資源複製的工作,如下:
If add...in class Human(public):
Human(Human &human):ID(human.getID())
{
name=new Name(human.getName()->getName());
}
OK,and you get :
They are the same one.
Press any key to continue
就沒問題了。
這次,我們來看看組合與繼承中的初始化問題,最後再說明物件陣列初始化需要注意的地方。主要是繼承的例子。我想澄清一些想法,強調一些觀念。當然,如果有爭議的地方,歡迎您給我指出。先謝過了。
大家知道,組合與繼承都是非常重要的耦合方式。典型的組合與繼承的例子,分別如下:
class Point{
int x,y;
//...
public:
//...
};
class Shape{
protected:
Point p0; //組合
//...
public:
Shape(int x,int y);
Shape(Point &point);
//...
};
class Window:public Shape{ //繼承
int width,height;
//...
public:
Window(int _x,int _y,int _w,int _h);
//...
};
在初始化時,可能是這樣的:
Window::Window(int _x,int _y,int _w,int _h):Shape(_x,_y),width(_w),height(_h)
{ } //(1)
組合與繼承的初始化,如果是我們自己來做這項工作,初始化的時機可只有這一個,(1)冒號後。這是c++的語法,沒有什麼可說的。
但是,我想,到現在,有些認識,需要得到強調。
首先,c++中的物件建立時必須得到初始化。一般的,我們要自己來做這項工作;但如果您沒有給出自己的建構函式,系統會給一個預設的建構函式,並去它(您知道它會做些什麼嗎?)。初始化是必須保證的。
其次,複雜類(組合繼承邇來)的初始化工作中,建構函式呼叫有固定的順序。一般的c++教材都說的很詳細,我就不多說了。
但有趣的是,複雜類中,若出現預設的系統初始化,都會發生些什麼?如果所有的父類都沒有寫建構函式,成員物件的類也沒有寫建構函式,又沒有常量成員和引用成員,一系列的初始化工作是按原來的順序,還是沒有初始化?這個問題也許沒有實際意義,但對理解初始化工作是很有意義的,我認為。
我們以繼承的初始化為例子,一步一步來看。
我們先來看看,如果不寫建構函式,系統會做什麼。
類的定義。首先,Shape是一個抽象基類(介面)。我沒有為它寫任何建構函式,讓系統來吧。
//shape.h
#pragma once
class Shape
{
protected:
int x,y;
public:
virtual ~Shape(void);
virtual void SetXY(int _x,int _y) = 0;
};
//shape.cpp
#include "shape.h"
#using
#include
Shape::~Shape(void)
{
}
下面是Shape類的一個子類實現,Window。為了對比測試,它有兩個建構函式,一個是無任何引數,不做任何事情,當然,我們可以假設不知道它會不會呼叫父類Shape的建構函式。另一個是正常的建構函式,但從父類
繼承的成員沒有在其中初始化(看系統如何做)。
//window.h
#pragma once
#include "shape.h"
class Window :
public Shape
{
int width,height;
public:
Window(void);
Window(int _x,int _y,int _w,int _h);
virtual ~Window(void);
virtual void SetXY(int _x, int _y);
void Test(void);
};
//window.cpp
#include
//建構函式1
Window::Window(void)
{
}
//建構函式2
Window::Window(int _x,int _y,int _w,int _h)
{
width=_w;
height=_h;
}
Window::~Window(void)
{
}
void Window::SetXY(int _x, int _y)
{
x=_x;
y=_y;
}
//
void Window::Test(void)
{
std::cout<}
這是公共的測試:
//fmain.cpp
#include
#include "window.h"
void main()
{
Window win2;
std::cout< win2.Test();
Window win(10,10,50,50);
std::cout< win.Test();
}
執行,結果如下:
Test:win2:
x=1243328,y=1243040,width=1303984,height=1243296
Test:win:
x=1243040,y=1,width=50,height=50
Press any key to continue
win2呼叫的是建構函式1,win呼叫的是建構函式2。win2的所有成員,值都似乎是隨機給的。而win中,只有width和height達到了預期效果,x和y和win2沒有什麼區別!
暫行記住,這是沒有寫建構函式的結果。
我們現在給Shape類新增建構函式,有兩個版本,作用同於上面Window類的建構函式。如下:
//shape.h
#pragma once
class Shape
{
protected:
int x,y;
public:
Shape(void);
Shape(int _x,int _y);
virtual ~Shape(void);
virtual void SetXY(int _x,int _y) = 0;
};
//shape.cpp
#include "shape.h"
#using
#include
//建構函式1:什麼也不做
Shape::Shape(void)
{
}
//建構函式2:履行初始化工作
Shape::Shape(int _x,int _y)
{
x=_x;
y=_y;
}
Shape::~Shape(void)
{
}
Window類的建構函式相應改正如下:
//建構函式1
Window::Window(void):Shape()
{
}
//建構函式2
Window::Window(int _x,int _y,int _w,int _h):Shape(_x,_y)
{
width=_w;
height=_h;
}
測試檔案程式碼不變。執行,結果如下:
Test:win2:
x=1243328,y=1243040,width=1303984,height=1243296
Test:win:
x=10,y=10,width=50,height=50
Press any key to continue
win2的情況沒有改觀,但win的初始化就是我們所要的!
這說明了什麼?如果您不明白,可以回頭對比看看。
系統的預設初始化,即使它給的值,是當時所在的地址的所有值(不可預料),但那仍然是初始化!
說到預設初始化,在欲建立物件陣列時要特別注意,如果沒有確省的建構函式,物件陣列是無法建立的,因為沒有合適的建構函式可呼叫!(如果不能初始化,是做出錯處理的)
Shape和Window類的建構函式相應改正如下:
//建構函式1:
Shape::Shape(void)
{
x=0;y=0;
}
//建構函式1
Window::Window(void):Shape()
{
width=0;height=0;
}
主函式中程式碼換為:
Window win[5];
for(int i=0;i<5;i++)
{
std::cout< win[i].Test();
}
則結果為:
Test:0:
x=0,y=0,width=0,height=0
Test:1:
x=0,y=0,width=0,height=0
Test:2:
x=0,y=0,width=0,height=0
Test:3:
x=0,y=0,width=0,height=0
Test:4:
x=0,y=0,width=0,height=0
Press any key to continue
但是,你把Shape類的建構函式1註釋掉(既刪除預設建構函式),再用同樣的測試檔案編譯時,編譯出錯:
Window.cpp(5) : error C2512: “Shape” : 沒有合適的預設建構函式可用
總之我想,這樣的觀念是必須的:
初始化工作必須完成。任何情況下,系統完成初始化工作的機理是不變的(建構函式呼叫順序),系統不會偷懶:)。我們需要設計良好的初始化過程。
這次遺留的問題是,所有的這些問題,在組合的情況下,也會發生嗎?在物件陣列初始化時,如果我們希望每個物件的初始化狀態都不同,應該如何做?如果您感覺不夠清晰,願您能寫程式碼測試一下,跟著結果思考:)。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-958280/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 談談c++的初始化工作(1) (轉)C++
- 談談c++的初始化工作(2) (轉)C++
- 談談c++的初始化工作(4) (轉)C++
- 談談專案的成本管理3(轉)
- 談談 C++ STL 中的迭代器C++
- 談談C++中的swap函式C++函式
- 談談軟體專案管理的重要性3(轉)專案管理
- 談談工作中的設計模式設計模式
- 再談c++型別轉換C++型別
- 談談創業公司技術的工作模式創業模式
- 談談對BPM的理解(轉)
- Matt Pietrek訪談,談他對.NET的看法及Numega工作情況(英文) (轉)
- 談談字串翻轉字串
- 談談專案的成本管理 (轉)
- 談談專案的成本管理(轉)
- 談談 ajax 工作過程那點事
- C/C++的思索 C++之父訪談錄 [上帝的玩笑嗎?] (轉)C++
- C++之父Bjarne談C++在2005年(轉)C++JAR
- 談談我工作中的23個設計模式設計模式
- 談談BPM、工作流引擎與OA的關係
- 談談專案的成本管理2 (轉)
- 談談redhat9 KDE的漢化(轉)Redhat
- 談談專案群組的管理 (轉)
- 談談Spring中的BeanPostProcessor介面(轉)SpringBean
- C++中的enum淺談C++
- 淺談國外工程專案的投標工作(轉)
- 談一談安全運營工作是什麼
- 近期的爬蟲工作雜談爬蟲
- 工作隨筆雜談
- C++程式設計雜談:物件導向 (轉)C++程式設計物件
- 談談IT專案中的溝通管理(轉)
- 程式設計師的經驗之談-生活與工作(轉)程式設計師
- 從移交驗收的角度談工程專案收尾工作(轉)
- C++ string (淺談)C++
- 談談App的統一跳轉和ARouterAPP
- 談談Live-cd版Linux的使用(轉)Linux
- 淺談Java中的例項初始化器Java
- C++——談談你對物件導向程式設計的認識C++物件程式設計