c++中使用建構函式初始化列表的情況

weixin_41874599發表於2019-01-15

C++類中成員變數的初始化有兩種方式:建構函式初始化列表和建構函式體內賦值。

一、內部資料型別(char,int……指標等)

  class Animal

  {

  public:

    Animal(int weight,int height): //A初始化列表

      m_weight(weight),

      m_height(height)

    {

    }

    Animal(int weight,int height) //B函式體內初始化

    {

      m_weight = weight;

      m_height = height;

    }

  private:

    int m_weight;

    int m_height;

  }

  對於這些內部型別來說,基本上是沒有區別的,效率上也不存在多大差異。

  當然A和B方式不能共存的。

二、無預設建構函式的繼承關係中

  class Animal

  {

  public: 

    Animal(int weight,int height): //沒有提供無參的建構函式

      m_weight(weight), 

      m_height(height)

    {

    }

  private:

    int m_weight;

    int m_height;

  };

 

  class Dog: public Animal

  {

  public:

    Dog(int weight,int height,int type) //error 建構函式 父類Animal無合適建構函式

    {

    }

  private:

    int m_type;

  }

  上面的子類和父類編譯會出錯:

  因為子類Dog初始化之前要進行父類Animal的初始化,但是根據Dog的建構函式,沒有給父類傳遞引數,使用了父類Animal的無引數建構函式。而父類Animal提供了有引數的建構函式,

  這樣編譯器就不會給父類Animal提供一個預設的無引數的建構函式了,所以編譯時報錯,說找不到合適的預設建構函式可用。要麼提供一個無引數的建構函式,

  要麼在子類的Dog的初始化列表中給父類Animal傳遞初始化引數,如下:

  class Dog: public Animal

  {

  public:

    Dog(int weight,int height,int type) : Animal(weight,height) //必須使用初始化列表增加對父類的初始化

    {

      this->m_type = type;

    }

  private:

    int m_type;

  }

三、類中const資料成員、引用資料成員,必須在初始化列表中初始化,不能使用賦值的方式初始化

  class Dog: public Animal

  {

  public:

    Dog(int weight,int height,int type) : Animal(weight,height),m_type (type),LEGS(4) //必須在初始化列表中初始化

    {

      this->m_type = type;//error

      //LEGS = 4; //error

    }

  private:

    int& m_type;

    const int LEGS;

  }

四、包含有自定義資料型別(類)物件的成員初始化 

  class Food

  {

  public:

    Food(int type = 10)

    {

      m_type = type;

    }

    Food(Food &other) //拷貝建構函式

    {

      m_type = other.m_type;

    }

    Food & operator =(Food &other) //過載賦值=函式

    {

      m_type = other.m_type;

      return *this;

    }

  private:

    int m_type;

  };

  (1)、建構函式賦值方式 初始化成員物件m_food

  class Dog: public Animal

  {

  public:

    Dog(Food &food)

      //:m_food(food)

    {

      m_food = food; //初始化 成員物件

    }

  private:

    Food m_food;

  };

  //使用

  Food fd;

  Dog dog(fd);

  結果:

  先執行了物件型別建構函式Food(int type = 10)

  然後再執行物件型別建構函式Food & operator =(Food &other)

  想象是為什麼?

  (2)、建構函式初始化列表方式

  class Dog: public Animal

  {

  public:

    Dog(Food &food) : m_food(food) //初始化 成員物件

    {

      //m_food = food;

    }

  private:

    Food m_food;

  };

  //使用

  Food fd;

  Dog dog(fd);

  結果:執行Food(Food &other)拷貝建構函式完成初始化

 

  不同的初始化方式得到不同的結果:明顯建構函式初始化列表的方式得到更高的效率。

相關文章