C++之类的构造函数初始化列表

下面给出代码,体会一下构造函数有无初始化列表的区别

#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;
}*/

//使用初始化列表,在函数体内无需操作
Student::Student(char* name,int age,float score):m_name(name),m_age(age),m_score(score){
    //TODO
}

Student::show(){
    cout<<m_name<<"age:"<<m_age<<",score:"<<m_score<<endl;
}

int main()
{
    Student stu("Ming",24,98);
    stu.show();
    Student *pstu= new Student("xu",28,89);
    pstu->show();
    return 0;
}

使用构造函数初始化列表并没有效率上的优势,仅仅是书写方便,尤其是成员变量较多时,这种写法非常简单明了。初始化列表还可以对部分变量进行初始化。

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。

初始化 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];
}

const用于类中成员变量时,将类成员变为只读属性(只读:不能出现在“=”的左边,但在类中仍可以用一个指针来修改其值。) 所以不可以直接在类的构造函数中初始化const 的成员。

那如果就想更改const成员变量呢,只能通过指针去改,如增加一个函数:

public:
void setlen(int len){
    int *plen=(int *)&m_len;
    *plen=len;      
}

 

posted @ 2020-07-01 15:59  njit-sam  阅读(370)  评论(0编辑  收藏  举报