構造函數的一項重要功能是對成員變量進行初始化,為了達到這個目的,可以在構造函數的函數體中對成員變量一一賦值,還可以采用參數初始化表。
參數初始化表使得代碼更加簡潔,請看下面的例子:
#include <iostream>
using namespace std;
class Student{
private:
char *m_name;
int m_age;
float m_score;
public:
Student(char *name, int age, float score);
void show();
};
//采用參數初始化表
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){
//TODO:
}
void Student::show(){
cout<<m_name<<"的年齡是"<<m_age<<",成績是"<<m_score<<endl;
}
int main(){
Student stu("小明", 15, 92.5f);
stu.show();
Student *pstu = new Student("李華", 16, 96);
pstu -> show();
return 0;
}
運行結果:
小明的年齡是15,成績是92.5
李華的年齡是16,成績是96
如本例所示,定義構造函數時並沒有在函數體中對成員變量一一賦值,其函數體為空(當然也可以有其他語句),而是在函數首部與函數體之間添加了一個冒號
:
,後面緊跟
m_name(name), m_age(age), m_score(score)
語句,這個語句的意思相當於函數體內部的
m_name = name; m_age = age; m_score = score;
語句,也是賦值的意思。
使用參數初始化表並沒有效率上的優勢,僅僅是書寫方便,尤其是成員變量較多時,這種寫法非常簡明明了。
參數初始化表可以用於全部成員變量,也可以只用於部分成員變量。下面的示例只對 m_name 使用參數初始化表,其他成員變量還是一一賦值:
Student::Student(char *name, int age, float score): m_name(name){
m_age = age;
m_score = score;
}
注意,參數初始化順序與初始化表列出的變量的順序無關,它只與成員變量在類中聲明的順序有關。請看代碼:
#include <iostream>
using namespace std;
class Demo{
private:
int m_a;
int m_b;
public:
Demo(int b);
void show();
};
Demo::Demo(int b): m_b(b), m_a(m_b){ }
void Demo::show(){ cout<<m_a<<", "<<m_b<<endl; }
int main(){
Demo obj(100);
obj.show();
return 0;
}
運行結果:
2130567168, 100
在參數初始化表中,我們將 m_b 放在了 m_a 的前面,看起來是先給 m_b 賦值,再給 m_a 賦值,其實不然!成員變量的賦值順序由它們在類中的聲明順序決定,在 Demo 類中,我們先聲明的 m_a,再聲明的 m_b,所以構造函數和下面的代碼等價:
Demo::Demo(int b): m_b(b), m_a(m_b){
m_a = m_b;
m_b = b;
}
給 m_a 賦值時,m_b 還未被初始化,它的值是不確定的,所以輸出的 m_a 的值是一個奇怪的數字;給 m_a 賦值完成後才給 m_b 賦值,此時 m_b 的值才是 100。
obj 在棧上分配內存,成員變量的初始值是不確定的。
初始化 const 成員變量
參數初始化表還有一個很重要的作用,那就是初始化 const 成員變量。初始化 const 成員變量的唯一方法就是使用參數初始化表。例如 VS/VC 不支持變長數組(數組長度不能是變量),我們自己定義了一個 VLA 類,用於模擬變長數組,請看下面的代碼:
class VLA{
private:
const int m_len;
int *m_arr;
public:
VLA(int len);
};
//必須使用參數初始化表來初始化 m_len
VLA::VLA(int len): m_len(len){
m_arr = new int[len];
}
VLA 類包含了兩個成員變量,m_len 和 m_arr 指針,需要注意的是 m_len 加了 const 修飾,只能使用參數初始化表的方式賦值,如果寫作下面的形式是錯誤的:
class VLA{
private:
const int m_len;
int *m_arr;
public:
VLA(int len);
};
VLA::VLA(int len){
m_len = len;
m_arr = new int[len];
}