C++建構函式—建構函式的宣告與定義、帶引數的建構函式
阿新 • • 發佈:2019-01-10
建構函式是一種隨著物件建立而自動被呼叫的函式,它的主要用途是為物件作初始化。那麼,建構函式到底是什麼樣子的呢?
//node.h
#include <iostream>//如果不包含iostream標頭檔案,這個檔案裡就不能用cout
using namespace std;
class Node//定義一個連結串列結點類
{
public:
……
Node();//建構函式的宣告,建構函式是公有的成員函式,沒有返回值型別
……
private:
int idata;//儲存資料保密
char cdata;//儲存資料保密
Node *prior;//前驅結點的儲存位置保密
Node *next;//後繼結點的儲存位置保密
};
Node::Node()//建構函式的定義
{
cout <<"Node constructor is running..." <<endl;//提示建構函式執行
idata=0;//初始化idata
cdata='0';//初始化cdata
prior=NULL;//初始化前驅結點指標
next=NULL;//初始化後續結點指標
}
這時,我們建立一個連結串列結點物件,建構函式隨著物件建立而自動被呼叫,所以這個物件建立之後idata的值為0,cdata的值為'0',prior和next的值都是NULL:(程式15.2.1)
//main.cpp
#include <iostream>
#include "node.h"
using namespace std;
int main()
{
Node a;//建立一個連結串列結點物件a,呼叫建構函式
cout <<a.readi() <<endl;
cout <<a.readc() <<endl;
return 0;
}
執行結果:
Node constructor is running...
0
0
可是,這樣的建構函式還是不太理想。如果每次初始化的值都是固定的,那麼有沒有建構函式都是一樣的。建構函式變成了一種擺設!我們該怎麼辦?
帶引數的建構函式
函式的特徵之一就是能夠在呼叫時帶上引數。既然建構函式也是函式,那麼我們就能給建構函式帶上引數,使用過載或預設引數等方法,從而實現更自由地對物件進行初始化操作。以下便是對連結串列結點類的進一步修改:(程式15.2.2)
//node.h
#include <iostream>
using namespace std;
class Node//定義一個連結串列結點類
{
public:
Node();//建構函式0
Node(int i,char c='0');//建構函式過載1,引數c預設為'0'
Node(int i,char c,Node *p,Node *n);//建構函式過載2
int readi() const;//讀取idata
char readc() const;//讀取cdata
Node * readp() const;//讀取上一個結點的位置
Node * readn() const;//讀取下一個結點的位置
bool set(int i);//過載,通過該函式修改idata
bool set(char c);//過載,通過該函式修改cdata
bool setp(Node *p);//通過該函式設定前驅結點
bool setn(Node *n);//通過該函式設定後繼結點
private:
int idata;//儲存資料保密
char cdata;//儲存資料保密
Node *prior;//前驅結點的儲存位置保密
Node *next;//後繼結點的儲存位置保密
};
int Node::readi() const//成員函式readi的定義
{
return idata;
}
char Node::readc() const
{
return cdata;
}
Node * Node::readp() const
{
return prior;
}
Node * Node::readn() const
{
return next;
}
bool Node::set(int i)//過載成員函式定義
{
idata=i;
return true;
}
bool Node::set(char c)
{
cdata=c;
return true;
}
bool Node::setp(Node *p)
{
prior=p;
return true;
}
bool Node::setn(Node *n)
{
next=n;
return true;
}
Node::Node()//建構函式0的定義
{
cout <<"Node constructor is running..." <<endl;//提示建構函式執行
idata=0;//初始化idata
cdata='0';//初始化cdata
prior=NULL;//初始化前驅結點指標
next=NULL;//初始化後續結點指標
}
Node::Node(int i,char c)//建構函式過載1,預設引數只需要在函式原型中出現
{
cout <<"Node constructor is running..." <<endl;
idata=i;
cdata=c;
prior=NULL;
next=NULL;
}
Node::Node(int i,char c,Node *p,Node *n)//建構函式過載2
{
cout <<"Node constructor is running..." <<endl;
idata=i;
cdata=c;
prior=p;
next=n;
}
//main.cpp
#include <iostream>
#include "node.h"
using namespace std;
int main()
{
Node a;//建立一個連結串列結點物件a,呼叫建構函式0
Node b(8);//建立一個連結串列結點物件b,呼叫建構函式過載1,引數c預設為'0'
Node c(8,'F',NULL,NULL);//建立一個連結串列結點物件c,呼叫建構函式過載2
cout <<a.readi() <<' ' <<a.readc() <<endl;
cout <<b.readi() <<' ' <<b.readc() <<endl;
cout <<c.readi() <<' ' <<c.readc() <<endl;
return 0;
}
執行結果:
Node constructor is running...
Node constructor is running...
Node constructor is running...
0 0
8 0
8 F
我們看到,在引數和過載的幫助下,我們可以設計出適合各種場合的建構函式。初始化各個物件的成員資料對我們來說已經是小菜一碟了。但是,這時你是否會回想起當初沒有編寫建構函式時的情形?如果沒有編寫建構函式,物件的建立是一個怎樣的過程呢?
建構函式的宣告與定義
在C++中,規定與類同名的成員函式就是建構函式。需要注意的是,建構函式應該是一個公有的成員函式,並且建構函式沒有返回值型別。以下是我們為連結串列結點類編寫的一個建構函式:(其他成員函式定義見14.3節)//node.h
#include <iostream>//如果不包含iostream標頭檔案,這個檔案裡就不能用cout
using namespace std;
class Node//定義一個連結串列結點類
{
public:
……
Node();//建構函式的宣告,建構函式是公有的成員函式,沒有返回值型別
……
private:
int idata;//儲存資料保密
char cdata;//儲存資料保密
Node *prior;//前驅結點的儲存位置保密
Node *next;//後繼結點的儲存位置保密
};
Node::Node()//建構函式的定義
{
cout <<"Node constructor is running..." <<endl;//提示建構函式執行
idata=0;//初始化idata
cdata='0';//初始化cdata
prior=NULL;//初始化前驅結點指標
next=NULL;//初始化後續結點指標
}
這時,我們建立一個連結串列結點物件,建構函式隨著物件建立而自動被呼叫,所以這個物件建立之後idata的值為0,cdata的值為'0',prior和next的值都是NULL:(程式15.2.1)
//main.cpp
#include <iostream>
#include "node.h"
using namespace std;
int main()
{
Node a;//建立一個連結串列結點物件a,呼叫建構函式
cout <<a.readi() <<endl;
cout <<a.readc() <<endl;
return 0;
}
執行結果:
Node constructor is running...
0
0
可是,這樣的建構函式還是不太理想。如果每次初始化的值都是固定的,那麼有沒有建構函式都是一樣的。建構函式變成了一種擺設!我們該怎麼辦?
帶引數的建構函式
函式的特徵之一就是能夠在呼叫時帶上引數。既然建構函式也是函式,那麼我們就能給建構函式帶上引數,使用過載或預設引數等方法,從而實現更自由地對物件進行初始化操作。以下便是對連結串列結點類的進一步修改:(程式15.2.2)//node.h
#include <iostream>
using namespace std;
class Node//定義一個連結串列結點類
{
public:
Node();//建構函式0
Node(int i,char c='0');//建構函式過載1,引數c預設為'0'
Node(int i,char c,Node *p,Node *n);//建構函式過載2
int readi() const;//讀取idata
char readc() const;//讀取cdata
Node * readp() const;//讀取上一個結點的位置
Node * readn() const;//讀取下一個結點的位置
bool set(int i);//過載,通過該函式修改idata
bool set(char c);//過載,通過該函式修改cdata
bool setp(Node *p);//通過該函式設定前驅結點
bool setn(Node *n);//通過該函式設定後繼結點
private:
int idata;//儲存資料保密
char cdata;//儲存資料保密
Node *prior;//前驅結點的儲存位置保密
Node *next;//後繼結點的儲存位置保密
};
int Node::readi() const//成員函式readi的定義
{
return idata;
}
char Node::readc() const
{
return cdata;
}
Node * Node::readp() const
{
return prior;
}
Node * Node::readn() const
{
return next;
}
bool Node::set(int i)//過載成員函式定義
{
idata=i;
return true;
}
bool Node::set(char c)
{
cdata=c;
return true;
}
bool Node::setp(Node *p)
{
prior=p;
return true;
}
bool Node::setn(Node *n)
{
next=n;
return true;
}
Node::Node()//建構函式0的定義
{
cout <<"Node constructor is running..." <<endl;//提示建構函式執行
idata=0;//初始化idata
cdata='0';//初始化cdata
prior=NULL;//初始化前驅結點指標
next=NULL;//初始化後續結點指標
}
Node::Node(int i,char c)//建構函式過載1,預設引數只需要在函式原型中出現
{
cout <<"Node constructor is running..." <<endl;
idata=i;
cdata=c;
prior=NULL;
next=NULL;
}
Node::Node(int i,char c,Node *p,Node *n)//建構函式過載2
{
cout <<"Node constructor is running..." <<endl;
idata=i;
cdata=c;
prior=p;
next=n;
}
//main.cpp
#include <iostream>
#include "node.h"
using namespace std;
int main()
{
Node a;//建立一個連結串列結點物件a,呼叫建構函式0
Node b(8);//建立一個連結串列結點物件b,呼叫建構函式過載1,引數c預設為'0'
Node c(8,'F',NULL,NULL);//建立一個連結串列結點物件c,呼叫建構函式過載2
cout <<a.readi() <<' ' <<a.readc() <<endl;
cout <<b.readi() <<' ' <<b.readc() <<endl;
cout <<c.readi() <<' ' <<c.readc() <<endl;
return 0;
}
執行結果:
Node constructor is running...
Node constructor is running...
Node constructor is running...
0 0
8 0
8 F
我們看到,在引數和過載的幫助下,我們可以設計出適合各種場合的建構函式。初始化各個物件的成員資料對我們來說已經是小菜一碟了。但是,這時你是否會回想起當初沒有編寫建構函式時的情形?如果沒有編寫建構函式,物件的建立是一個怎樣的過程呢?
在C++中,每個類都有且必須有建構函式。如果使用者沒有自行編寫建構函式,則C++自動提供一個無引數的建構函式,稱為預設建構函式。這個預設建構函式不做任何初始化工作。一旦使用者編寫了建構函式,則這個無引數的預設建構函式就消失了。如果使用者還希望能有一個無引數的建構函式,必須自行編寫。