C++ ─── 初始化列表(类和对象)

本文详细解释了C++中构造函数体赋值与初始化列表的区别,强调了初始化列表的使用原则,以及explicit关键字在单参构造函数中的类型转换限制。
摘要由CSDN通过智能技术生成

目录

1.1 构造函数体赋值

1.2 初始化列表

1.3 explicit关键字


1.1 构造函数体赋值

        在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。
class Date
{
public:
 Date(int year, int month, int day)
 {
 _year = year;
 _month = month;
 _day = day;
 }
private:
 int _year;
 int _month;
 int _day;
};
        虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化,
        构造函数体中的语句只能将其称为 赋初值 ,而 不能称作初始化 。因为 初始化只能初始化一次,而构造函数体 内可以多次赋值

1.2 初始化列表

        初始化列表:以一个 冒号开始 ,接着是一个以 逗号分隔 的数据成员列表 ,每个 " 成员变量 " 后面跟一个 放在 括号中 的初始值或表达式。
class Date
{
public: Date(int year, int month, int day)
     : _year(year)
     , _month(month)
     , _day(day)
 {}
 
private:
     int _year;
     int _month;
     int _day;
};
【注意】
        1. 每个成员变量在初始化列表中 只能出现一次 ( 初始化只能初始化一次 )
        2. 类中包含以下成员,必须放在初始化列表位置进行初始化:
                ★引用成员变量
                ★const成员变量
                ★自定义类型成员(且该类没有默认构造函数时)
class A
{
public:
     A(int a)
     :_a(a)
     {}

private:
     int _a;
};

class B
{
public:

     B(int a, int ref)
     :_aobj(a)
     ,_ref(ref)
     ,_n(10)
     {}

private:
     A _aobj; // 没有默认构造函数
     int& _ref; // 引用
     const int _n; // const 
};
        3. 尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。
        4. 成员变量 在类中 声明次序 就是其在初始化列表中的 初始化顺序 ,与其在初始化列表中的先后次序无关
class A
{
public:
     A(int a)
     :_a1(a)
     ,_a2(_a1)
     {}
 
 void Print() 
{
 cout<<_a1<<" "<<_a2<<endl;
}

private:
     int _a2;
     int _a1;
};

int main() 
{
     A aa(1);
     aa.Print();
}    
A. 输出1 1
B.程序崩溃
C.编译不通过
D.输出1 随机值

答案:D

1.3 explicit关键字

        构造函数不仅可以构造与初始化对象,对于接收单个参数的构造函数,还具有 类型转换 的作用
        接收单个参数的构造函数具体表现:
        1. 构造函数只有一个参数
        2. 构造函数有多个参数,除第一个参数没有默认值外,其余参数都有默认值
        3. 全缺省构造函数
class Date
{
public:
 // 1. 单参构造函数,没有使用explicit修饰,具有类型转换作用
 // explicit修饰构造函数,禁止类型转换---explicit去掉之后,代码可以通过编译
     explicit Date(int year)
     :_year(year)
     {}
 /*
     // 2. 虽然有多个参数,但是创建对象时后两个参数可以不传递,没有使用explicit修饰,具有类型转换作用
     // explicit修饰构造函数,禁止类型转换
     explicit Date(int year, int month = 1, int day = 1)
     : _year(year)
     , _month(month)
     , _day(day)
     {}
 */

     Date& operator=(const Date& d)
     {
         if (this != &d)
         {
             _year = d._year;
             _month = d._month;
             _day = d._day;
         }
         return *this;
     }

private:
     int _year;
     int _month;
     int _day;
};

void Test()
{
     Date d1(2022);
 // 用一个整形变量给日期类型对象赋值
 // 实际编译器背后会用2023构造一个无名对象,最后用无名对象给d1对象进行赋值
     d1 = 2023;
 // 将1屏蔽掉,2放开时则编译失败,因为explicit修饰构造函数,禁止了单参构造函数类型转换的作用
}
上述代码可读性不是很好, explicit 修饰构造函数,将会禁止构造函数的隐式转换

这个博客如果对你有帮助,给博主一个免费的点赞就是最大的帮助

欢迎各位点赞,收藏和关注哦

如果有疑问或有不同见解,欢迎在评论区留言哦

后续我会一直分享双一流211西北大学软件(C,数据结构,C++,Linux,MySQL)的学习干货以及重要代码的分享

  • 23
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一码归—码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值