歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

C++拾遺--構造函數

前言

對一個類而言,構造函數恐怕是最重要的一個成員函數了。關於構造函數的細節繁多,並且隨著新標准的提出,構造函數有了新的特性。本文來集中探討下構造函數的那些鮮為人知的一面。

構造函數

構造函數的作用眾所周知:在類的對象被創建時,控制對象的初始化和賦值。

構造函數的一般形式:

類名(arg_list);

其中arg_list是用逗號隔開的參數列表。

特點:無返回值類型,且不可加const限制。

默認構造函數

需要特別指出,無參的構造函數是默認的,有參但都有默認參數的構造函數也是默認構造。

------------------------------分割線------------------------------

C++ Primer Plus 第6版 中文版 清晰有書簽PDF+源代碼 http://www.linuxidc.com/Linux/2014-05/101227.htm

讀C++ Primer 之構造函數陷阱 http://www.linuxidc.com/Linux/2011-08/40176.htm

讀C++ Primer 之智能指針 http://www.linuxidc.com/Linux/2011-08/40177.htm

讀C++ Primer 之句柄類 http://www.linuxidc.com/Linux/2011-08/40175.htm

將C語言梳理一下,分布在以下10個章節中:

  1. Linux-C成長之路(一):Linux下C編程概要 http://www.linuxidc.com/Linux/2014-05/101242.htm
  2. Linux-C成長之路(二):基本數據類型 http://www.linuxidc.com/Linux/2014-05/101242p2.htm
  3. Linux-C成長之路(三):基本IO函數操作 http://www.linuxidc.com/Linux/2014-05/101242p3.htm
  4. Linux-C成長之路(四):運算符 http://www.linuxidc.com/Linux/2014-05/101242p4.htm
  5. Linux-C成長之路(五):控制流 http://www.linuxidc.com/Linux/2014-05/101242p5.htm
  6. Linux-C成長之路(六):函數要義 http://www.linuxidc.com/Linux/2014-05/101242p6.htm
  7. Linux-C成長之路(七):數組與指針 http://www.linuxidc.com/Linux/2014-05/101242p7.htm
  8. Linux-C成長之路(八):存儲類,動態內存 http://www.linuxidc.com/Linux/2014-05/101242p8.htm
  9. Linux-C成長之路(九):復合數據類型 http://www.linuxidc.com/Linux/2014-05/101242p9.htm
  10. Linux-C成長之路(十):其他高級議題

舉例證明:

#include <iostream>
using namespace std;

class MyClass
{
protected:
 int a = 0;
 int b{1};
public:
 MyClass(int a = 0, int b = 0):a(a), b(b)  //有默認實參的構造方法就是默認構造
 {
  cout << "MyClass(int a = 0, int b = 0)" << endl;
 }

 int getA()const
 {
  return a;
 }
 int getB()const
 {
  return b;
 }
};
int main()
{
 MyClass my;  //調用默認構造
 cout << "a = " << my.getA() << ends << "b = " << my.getB() << endl;
 cin.get();
 return 0;
}

運行

從運行結果,即可驗證結論。有參但都有默認參數的構造函數也是默認構造,這一點恐怕是很多人都容易忽略的、

默認構造初始化類的數據成員的規則:

如果存在類內的初始值,用它來初始化成員。

否則,默認初始化。(這個規則雖是標准,但大多數編譯器還做不到)

幾個概念

1.類內初始值。

在上例代碼中,int a = 0; int b{1};這種形式就是類內初始值。後面會說明何時使用類內初始值。

2.默認初始化。

內置類型,如int,double類型等。int->0,double->0.0。就是默認初始化。

類類型,使用該類的默認構造初始化,就是默認初始化。

默認構造並不是總是存在的,若有另一個構造函數(非默認構造)存在,則編譯器並不會提供一個無參的默認構造。新標准提出了一種方式:如 MyClass() = default; 關鍵字 default 的這種使用,表明要求編譯器生成一個默認的構造函數。

3.初始值列表

構造函數 MyClass(int a = 0, int b = 0):a(a), b(b){...}  其中 a(a), b(b)就是初始值列表。

4.什麼是初始化?什麼是賦值?

對象在內存中創建(有了內存實體),第一次有的值,叫做初始化。把原先的值覆蓋掉,叫做賦值。

一般情況下,構造函數在初始值列表中完成初始化,在函數體中完成賦值。

這個結論並不好證明,但還是有辦法的,辦法就是借助:const類型和引用類型。如下代碼:

#include <iostream>
using namespace std;

class MyClass
{
protected:
 int a = 0;
 const int ca = 0;
 int& ra;
public:
 MyClass(int a) :a(a), ca(a), ra(this->a){}
 int getA()const
 {
  return a;
 }
 void printCa()const
 {
  cout << "ca = " << ca << endl;
 }
 void printRa()const
 {
  cout << "ra = " << ra << endl;
 }
};
int main()
{
 MyClass my(1);
 cout << my.getA() << endl;
 my.printCa();
 my.printRa();
 cin.get();
 return 0;
}

運行

const類型和引用類型,在創建時,必須進行初始化。若是把 ca = a; ra = this->a; 移到構造函數體內部,則無法通過編譯。也就是說,一旦進入構造函數體,初始化就已經完成了。

需要指出,初始值列表的順序並不代表著實際初始變量的順序,而成員的聲明順序才是。

更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2015-02/113672p2.htm

Copyright © Linux教程網 All Rights Reserved