建構子(constructor)
建構子是什麼呢?建構子是從什麼樣的觀念演化過來的呢?不曉得沒有關係,現在一步一步
帶你走進它的歷史。假設對C++的認知中,類別(class)中只存在函數與變數,而沒有什麼所謂
的建構子(constructor)、解構子(destructor)、…等,那要如何撰寫這個類別呢?舉個例子:
::::::::::::::::::::::::::::::::::::::::::::::
#include<iostream>
using namespace std;
class
People
{
private:
int age;
public:
void Initial(int _age)
{
age = _age;
}
int GetAge( )
{
return age;
}
};
void
main( )
{
People james;
james.Initial(20);
cout<<"James's age : "<<james.GetAge(
)<<endl;
}
::::::::::::::::::::::::::::::::::::::::::::::
輸出:James's age : 20
Initial(...)這個函數從字面上應該就可以知道它的作用,就是初始化但你會不會覺得很麻煩呢?
在宣告的時候為什麼不一起初始化它,而要呼叫Initial(...)來初始化呢?我想這個問題不只我想
到,你應該也觀察到了,所以在C++中,使用了一個特別的成員函數(Special member function)
來產生(Create)並初始化(Initialize)物件(Object),這個特別的成員函數,稱之為建構子(Constructor)。
舉個例子:
::::::::::::::::::::::::::::::::::::::::::::::
#include<iostream>
using namespace std;
class People
{
private:
int age;
public:
People()
{
cout<<"Constructor!!!"<<endl;
}
};
void main( )
{
People james;
}
::::::::::::::::::::::::::::::::::::::::::::::
輸出:Constructor!!!
在宣告變數james,會去呼叫建構子People(),而輸出"Constructor!!!"
有沒有注意到,建構子People()與類別同名(Same
Name as the class)哦!
這是建構子的語法之一,另外發現到了嗎?建構子沒有回傳值(No
Return Value),
這也是建構子的語法之一,另外有沒有發現到建構子參數列(Parameter list)中,
沒有任何的參數,那就不是建構子的語法囉!!!那是因為還沒有討論到,慢慢來!!!
上一個例子,沒有做任何初始化的動作,接下來看個有初始化的例子:
::::::::::::::::::::::::::::::::::::::::::::::
#include<iostream>
using namespace std;
class People
{
private:
int age;
public:
People(int _age)
{
cout<<"Constructor!!!"<<endl
;
age = _age
;
}
void Display()
{
cout<<"Age
:"<<age<<endl;
}
};
void main( )
{
People james(20);
james.Display();
}
::::::::::::::::::::::::::::::::::::::::::::::
輸出:
Constructor!!!
Age :20
建構子People(...),具有一個參數用來初始化資料成員(Data
member)age
當一開始執行時People james(20);時,呼叫建構子,輸出"Constructor!!!"
並將_age = 20 的值指定給資料成員age,建構子呼叫結束,之後執行james.Display顯示age的值。
說明:
(1)
People james(20);在此可以改寫為: People james = 20;
這是一個Equivalent Syntax,而不是Assignment Statement.
這似乎會難人感到些許的困惑,會讓人把"="看作是Assignment
不管你是否喜歡這種用法,你必須看得懂.
Assignment Statement是什麼呢?舉個例子: num1 = num2;
(2)
一個參數的建構子(One-Argument Constructor),另一個名稱為轉換函數(Conversion function),
它將另一個資料型態轉成另一個資料型態:
People james(20); //建構子將整數型態數值20轉換成People的資料型態
除了一個參數的建構子外,當然還有Two-Argument Constructor, No-Argument Constructor,...等,
觀念是一樣的。接著來介紹複製建構子(Copy constructors),那它什麼時候會被呼叫呢?當以一
個已存在的object來產生並初始化另一個object時,Copy constructor會被呼叫,而什麼場合的時候
會被呼叫呢?常見的兩個場合:
(1)Pass by Value的方式
(2)Return by Value的方式
很模糊吧!!!別急,先來看看Copy constructor的型式,舉個例子:
::::::::::::::::::::::::::::::::::::::::::::::
#include<iostream>
using namespace std;
class People
{
private:
int age;
public:
People(int _age)
{
cout<<"Constructor!!!"<<endl ;
age = _age ;
}
People(const People& _People)
{
cout<<"Copy Constructor!!!"<<endl;
age = _People.age;
}
void Display()
{
cout<<"Age :"<<age<<endl;
}
};
void main( )
{
People james=20; //Calling the constructor!!!
People tkd = james; //Calling copy constructor to create tkd
james.Display();
tkd.Display();
}
:::::::::::::::::::::::::::::::::::::::::::::: 輸出: Constructor!!! Copy Constructor!!! Age :20 Age :20
Copy constructor的型式People(const People& _People);
(1)參數必須以Pass by Reference的方式
若以Pass by Value的方式會有什麼結果呢?
那來研究看看Copy constructor以Pass by Value的方式。
執行到People tkd = james;時
tkd呼叫Copy
constructor:
People(const People _People){ ... },此時james傳給_People:
^^^^^^^^^^^^^^^^^^
const People _People = james;
此時_People呼叫Copy
constructor
People(const People _People){ ... },此時將james傳給_People:
^^^^^^^^^^^^^^^^^^
const People _People = james;
此時_People呼叫Copy constructor
...infinite(一直執行到電腦的堆疊溢位或是發生錯誤)
所以以Pass by Value的方式是不被compiler許可的,各位不妨試試看。
那什麼是Pass by Reference呢?如果還不知道,那你應該不適合看此文章囉!!!
(2)參數應該是const,因為你只是利用已存在的object來產生並初始化object
而不應該改變已存在的object內的內容!!!
來介紹什麼場合會呼叫Copy constructor,舉個例子:
::::::::::::::::::::::::::::::::::::::::::::::
#include<iostream> using namespace std; class People { private: int age;
public:
People(int _age)
{
cout<<"Constructor!!!"<<endl ;
age = _age ;
}
People(const People& _People)
{
cout<<"Copy Constructor!!!"<<endl;
age = _People.age;
}
void Display()
{
cout<<"Age :"<<age<<endl;
}
};
void func(People _People){}
void main( )
{
People james=20;
james.Display();
func(james);
}
:::::::::::::::::::::::::::::::::::::::::::::: 輸出: Constructor!!! Age :20 Copy Constructor!!!
當呼叫func函數時void
func(People _People){}
People _People = james;
會呼叫Copy constructor!!!
再舉個例子:
::::::::::::::::::::::::::::::::::::::::::::::
#include<iostream>
using namespace std;
class People
{
private:
int age;
public:
People()
{
cout<<"Default Constructor!!!"<<endl;
}
People(int _age)
{
cout<<"Constructor!!!"<<endl ;
age = _age ;
}
People(const People& _People)
{
cout<<"Copy Constructor!!!"<<endl;
age = _People.age;
}
void Display()
{
cout<<"Age :"<<age<<endl;
}
};
People func()
{
People temp;
return temp;
}
void main( )
{
People james=20;
james.Display();
func();
}
:::::::::::::::::::::::::::::::::::::::::::::: 輸出: Constructor!!! Age :20 Default Constructor!!! Copy Constructor!!!
當呼叫func()時,為什麼會呼叫Copy Constructor呢?重點在於return temp
注意看func()回傳值的傳遞方式是以return by value,所以return時會copy
一份temp的值儲存在一個臨時物件(temporary object),此時會呼叫Copy
Constructor!!在如果將func()的內容改為這樣:
People
func()
{
return People(10);
}
那請問各位是會呼叫Copy
Constructor還是Constructor呢?你應該答得出來滴!!!
Ans:Constructor!!!
Written By James On 2004/02/08