1. 程式人生 > >十八、初始化列表的使用

十八、初始化列表的使用

空間 vat 無法 正在 直接 出現 對象創建 意義 c++

1、類中定義const成員,及其初始化

#include <stdio.h>
class Test
{
private:
    const int ci;   // 編譯通過,類中可以用const來修飾
public:
    int getCI() 
    { 
        return ci; 
    }
};

int main()
{
    Test t; // 定義t對象的時候,報錯說ci沒有初始化
    
    printf("t.ci = %d\n", t.getCI());
    
    return 0;
}

如何初始化類裏面的const成員?

首先考慮構造函數初始化

class Test
{
private:
    const int ci;   // 得到的是只讀變量,不能作為左值
    // 初始化必須在這裏進行
public:
    Test()
    {
        ci = 10;    // ci是只讀成員變量,不能修改,報錯
    }
    int getCI()
    {
        return ci;
    }
}

於是出現了初始化列表

C++中提供了初始化列表對成員變量進行初始化

語法規則:

// 構造函數
// 初始化列表在構造函數的地方使用
// 在構造函數的定義之後,函數體之前,加 :號,初始化列表對成員變量進行初始化
// 用v1對m1進行初始化,用v1,v2對m2進行初始化,用v3對m3進行初始化
ClassName::ClassName() : m1(v1), m2(v1,v2), m3(v3)
{}

通過初始化列表對ci 進行初始化

class Test
{
private:
    const int ci;
public:
    Test():ci(10)   // 編譯通過,用初始化列表的方式初始化了const只讀成員變量,初始化之後,還是可以通過指針的方式修改這個值,只是ci不能做左值
    {
        // ci = 10;
    }
    int getCI() 
    { 
        return ci; 
    }
};

類成員的初始化, 註意事項:

  • 成員的初始化順序與成員的申明順序相同
  • 成員的初始化順序與初始化列表中的位置無關
  • 初始化列表先於構造函數的函數體執行
// 初始化順序和初始化列表無關,和聲明順序相同
ClassName::ClassName() : m1(v1), m2(v1,v2), m3(v3)
{}

構造函數是在對象創建完成之後,再調用構造函數進行成員變量的初始化,其實是一個成員變量的賦值函數,並非真正意義上的初始化

初始化列表則是在對象創建的同時就對對象進行了初始化,順序先於構造函數函數體

區別類似於變量的初始化和賦值

int a = 1;  // 類似於初始化列表

int a;
a = 1;      // 類似於構造函數
#include <stdio.h>

class Value
{
private:
    int mi;
public:
    Value(int i)
    {
        printf("i = %d\n", i);
        mi = i;
    }
    int getI()
    {
        return mi;
    }
};

class Test
{
private:
    Value m2;   // Value 類創建的對象,帶了1個參數
    // Value m2(2); // err
    Value m3;
    Value m1;
public:
    Test() : m1(1), m2(2), m3(3)    // 使用初始化列表來進行初始化
    {
        printf("Test::Test()\n");
    }
};


int main()
{
    Test t;     // 打印列表是 2 3 1 , 順序按照成員變量聲明順序
    
    return 0;
}

類中的const成員

  • 類中的const成員會被分配空間
  • 類中的const成員本質是只讀變量
  • 類中的const成員只能在初始化列表中制定初始值

編譯器無法直接得到const成員的初始值,因此無法進入符號表成為真正意義上的常量。

const成員分配的空間的位置和當前對象一樣,對象在棧區,const成員就在棧區

#include <stdio.h>

class Value
{
private:
    int mi;
public:
    Value(int i)
    {
        printf("i = %d\n", i);
        mi = i;
    }
    int getI()
    {
        return mi;
    }
};

class Test
{
private:
    const int ci;
    Value m2;
    Value m3;
    Value m1;
public:
    Test() : m1(1), m2(2), m3(3), ci(100)
    {
        printf("Test::Test()\n");
    }
    int getCI()
    {
        return ci;
    }
    int setCI(int v)
    {
        int *p = const_cast<int *>(&ci);    // 用指針改變const成員變量的值       
        *p = v;
    }
};

int main()
{
    Test t;
    
    printf("t.ci = %d\n", t.getCI());
    
    t.setCI(10);
    
    printf("t.ci = %d\n", t.getCI());
    
    return 0;
}

初始化與賦值的區別:

初始化:對正在創建的對象進行初始值設置

賦值:對已經存在的對象進行值設置

2、小結

類中可以使用初始化裏列表對成員進行初始化

初始化列表先於構造函數體進行

類中可以定義const成員變量

const成員變量必須在初始化列表中指定初值

const成員變量為只讀變量

十八、初始化列表的使用