c++基本使用(构造函数的初始化列表)

构造函数的初始化列表

语法:

    CGirl(string name, int age, CBoy& boy) :m_name(name), m_age(age),m_boy(boy)      // 三个参数的普通构造函数。
    {
        cout << "调用了CGirl(name,age,boy)构造函数。\n";
    }
  1. 如果成员已经在初始化列表中,则不应该在构造函数中再次赋值。
  2. 初始化列表的括号中可以是具体的值,也可以是构造函数的形参名,还可以是表达式。
  3. 初始化列表与赋值有本质的区别,如果成员是类,使用初始化列表调用的是成员类的拷贝构造函数,而赋值则是先创建成员类的对象(将调用成员类的普通构造函数),然后再赋值。
  4. 如果成员是类,初始化列表对性能略有提升。
  5. 如果成员是常量和引用,必须使用初始列表,因为常量和引用只能在定义的时候初始化。
  6. 如果成员是没有默认构造函数的类,则必须使用初始化列表。
  7. 拷贝构造函数也可以有初始化列表。
  8. 类的成员变量可以不出现在初始化列表中。
  9. 构造函数的形参先于成员变量初始化。

1的例子:

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。



class CGirl                 // 超女类CGirl。
{
public:
    string    m_name;                     // 姓名属性。
    int         m_age;                         // 年龄属性。
    CGirl():m_name("西施"),m_age(22)                                       // 没有参数的普通构造函数,默认构造函数。  
    {  
        m_name="赋值后的西施";
        cout << "调用了CGirl()构造函数。\n"; 
    }
    //CGirl(string name, int age,CBoy &boy)     // 三个参数的普通构造函数。
    //{
    //    m_name = name; m_age = age; m_boy.m_xm = boy.m_xm;
    //    cout << "调用了CGirl(name,age,boy)构造函数。\n";
    //}
    CGirl(string name, int age) :m_name(name), m_age(age)   // 三个参数的普通构造函数。
    {
        cout << "调用了CGirl(name,age,boy)构造函数。\n";
    }
    // 超女自我介绍的方法,显示姓名、年龄、男朋友。
    void show() { cout << "姓名:" << m_name << ",年龄:" << m_age << endl; }
};

int main()
{
    CGirl g1;
    
    g1.show();
}

2的例子:

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。


class CGirl                 // 超女类CGirl。
{
public:
    string    m_name;                     // 姓名属性。
    const int         m_age;                         // 年龄属性。

    //CGirl()                                       // 没有参数的普通构造函数,默认构造函数。  
    //{  
    //    cout << "调用了CGirl()构造函数。\n"; 
    //}
    //CGirl(string name, int age,CBoy &boy)     // 三个参数的普通构造函数。
    //{
    //    m_name = name; m_age = age; m_boy.m_xm = boy.m_xm;
    //    cout << "调用了CGirl(name,age,boy)构造函数。\n";
    //}
    CGirl(string name, int age) :m_name(name), m_age(age+100)     // 三个参数的普通构造函数。
    {
        cout << "调用了CGirl(name,age,boy)构造函数。\n";
    }
    // 超女自我介绍的方法,显示姓名、年龄、男朋友。
    void show() { cout << "姓名:" << m_name << ",年龄:" << m_age << endl; }
};

int main()
{
    
    CGirl g1("冰冰",18);
    
    g1.show();
}

3的例子:
使用初始化列表,

  1. 先调用的是成员类的拷贝构造函数,
  2. 而赋值则是先创建成员类的对象(将调用成员类的普通构造函数),
  3. 然后再赋值

总结就是:先初始化构造函数的形参对象boy(使用拷贝构造函数,从实参对象CBoy boy("子都");拷贝过来),然后初始化类成员(使用普通构造函数初始化类成员m_boy

区分了(数据传递的方向是)实参–>形式参数–>类成员

拷贝构造函数
这一篇博文保姆级详细的解释了这个传参中,构造函数调用的问题

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。

class CBoy                // 男朋友类。
{
public:
    string m_xm;                      // 男朋友的姓名。
    CBoy()                                 // 没有参数的普通构造函数,默认构造函数。  
    { m_xm.clear();  cout << "调用了CBoy()构造函数。\n"; }
    CBoy(string xm)                 // 有一个参数的普通构造函数。  
    { m_xm = xm;  cout << "调用了CBoy(string xm)构造函数。\n"; }
    CBoy(const CBoy& bb)     // 默认拷贝构造函数。  
    { m_xm = bb.m_xm;  cout << "调用了CBoy(const CBoy &bb)拷贝构造函数。\n"; }
};

class CGirl                 // 超女类CGirl。
{
public:
    string    m_name;                     // 姓名属性。
    int         m_age;                         // 年龄属性。
    CBoy     m_boy;                         // 男朋友的信息。

    CGirl()                                       // 没有参数的普通构造函数,默认构造函数。  
    {  
       cout << "调用了CGirl()构造函数。\n"; 
    }

    CGirl(string name, int age, CBoy boy) :m_name(name), m_age(age)      // 三个参数的普通构造函数。
    {
        m_boy.m_xm = boy.m_xm;
        cout << "调用了CGirl(name,age,boy)构造函数。\n";
    }
    // 超女自我介绍的方法,显示姓名、年龄、男朋友。
    void show() { cout << "姓名:" << m_name << ",年龄:" << m_age << ",男朋友:" << m_boy.m_xm << endl; }
};

int main()
{
    CBoy boy("子都");

    CGirl g1("冰冰",18,boy);
    
    g1.show();
}

将构造函数中的类形参改为引用,则不调用拷贝构造函数了
(省去了之前实参向形参传值调用的那个拷贝构造函数)

    CGirl(string name, int age, CBoy& boy) :m_name(name), m_age(age)      // 三个参数的普通构造函数。
    {
        m_boy.m_xm = boy.m_xm;
        cout << "调用了CGirl(name,age,boy)构造函数。\n";
    }
#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。

class CBoy                // 男朋友类。
{
public:
    string m_xm;                      // 男朋友的姓名。
    CBoy()                                 // 没有参数的普通构造函数,默认构造函数。  
    { m_xm.clear();  cout << "调用了CBoy()构造函数。\n"; }
    CBoy(string xm)                 // 有一个参数的普通构造函数。  
    { m_xm = xm;  cout << "调用了CBoy(string xm)构造函数。\n"; }
    CBoy(const CBoy& bb)     // 默认拷贝构造函数。  
    { m_xm = bb.m_xm;  cout << "调用了CBoy(const CBoy &bb)拷贝构造函数。\n"; }
};

class CGirl                 // 超女类CGirl。
{
public:
    string    m_name;                     // 姓名属性。
    int         m_age;                         // 年龄属性。
    CBoy     m_boy;                         // 男朋友的信息。

    CGirl()                                       // 没有参数的普通构造函数,默认构造函数。  
    {  
       cout << "调用了CGirl()构造函数。\n"; 
    }

    CGirl(string name, int age, CBoy& boy) :m_name(name), m_age(age)      // 三个参数的普通构造函数。
    {
        m_boy.m_xm = boy.m_xm;
        cout << "调用了CGirl(name,age,boy)构造函数。\n";
    }
    // 超女自我介绍的方法,显示姓名、年龄、男朋友。
    void show() { cout << "姓名:" << m_name << ",年龄:" << m_age << ",男朋友:" << m_boy.m_xm << endl; }
};

int main()
{
    CBoy boy("子都");

    CGirl g1("冰冰",18,boy);
    
    g1.show();
}

使用初始化列表,则:初始化类成员调用拷贝构造函数了
(之前没有使用初始化列表,初始化类成员调用普通构造函数。。)

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。

class CBoy                // 男朋友类。
{
public:
    string m_xm;                      // 男朋友的姓名。
    CBoy()                                 // 没有参数的普通构造函数,默认构造函数。  
    { m_xm.clear();  cout << "调用了CBoy()构造函数。\n"; }
    CBoy(string xm)                 // 有一个参数的普通构造函数。  
    { m_xm = xm;  cout << "调用了CBoy(string xm)构造函数。\n"; }
    CBoy(const CBoy& bb)     // 默认拷贝构造函数。  
    { m_xm = bb.m_xm;  cout << "调用了CBoy(const CBoy &bb)拷贝构造函数。\n"; }
};

class CGirl                 // 超女类CGirl。
{
public:
    string    m_name;                     // 姓名属性。
    int         m_age;                         // 年龄属性。
    CBoy     m_boy;                         // 男朋友的信息。

    CGirl()                                       // 没有参数的普通构造函数,默认构造函数。  
    {  
       cout << "调用了CGirl()构造函数。\n"; 
    }

    CGirl(string name, int age, CBoy& boy) :m_name(name), m_age(age),m_boy(boy)      // 三个参数的普通构造函数。
    {
        // m_boy.m_xm = boy.m_xm;
        cout << "调用了CGirl(name,age,boy)构造函数。\n";
    }
    // 超女自我介绍的方法,显示姓名、年龄、男朋友。
    void show() { cout << "姓名:" << m_name << ",年龄:" << m_age << ",男朋友:" << m_boy.m_xm << endl; }
};

int main()
{
    CBoy boy("子都");

    CGirl g1("冰冰",18,boy);
    
    g1.show();
}

5的例子:

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。

class CBoy                // 男朋友类。
{
public:
    string m_xm;                      // 男朋友的姓名。
    CBoy()                                 // 没有参数的普通构造函数,默认构造函数。  
    { m_xm.clear();  cout << "调用了CBoy()构造函数。\n"; }
    CBoy(string xm)                 // 有一个参数的普通构造函数。  
    { m_xm = xm;  cout << "调用了CBoy(string xm)构造函数。\n"; }
    CBoy(const CBoy& bb)     // 默认拷贝构造函数。  
    { m_xm = bb.m_xm;  cout << "调用了CBoy(const CBoy &bb)拷贝构造函数。\n"; }
};

class CGirl                 // 超女类CGirl。
{
public:
    string    m_name;                     // 姓名属性。
    const int         m_age;                         // 年龄属性。
    CBoy&     m_boy;                         // 男朋友的信息。

    // CGirl(string name, int age, CBoy& boy)      // 三个参数的普通构造函数。
    // {
    //     m_name = name;
    //     m_age = age;
    //     m_boy.m_xm = boy.m_xm;
    //     cout << "调用了CGirl(name,age,boy)构造函数。\n";
    // }
    CGirl(string name, int age, CBoy& boy):m_name(name),m_age(age),m_boy(boy)      // 三个参数的普通构造函数。
    {
        cout << "调用了CGirl(name,age,boy)构造函数。\n";
    }
    // 超女自我介绍的方法,显示姓名、年龄、男朋友。
    void show() { cout << "姓名:" << m_name << ",年龄:" << m_age << ",男朋友:" << m_boy.m_xm << endl; }
};

int main()
{
    CBoy boy("子都");

    CGirl g1("冰冰",18,boy);
    
    g1.show();
}

类形参改为引用,则不调用拷贝构造函数了
类成员改为引用,则不调用拷贝构造函数了(使的是初始化列表)
在这里插入图片描述

如果都不使用引用,则是如下的结果:

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值