ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

7-5 构造函数再探

2022-02-20 08:31:14  阅读:136  来源: 互联网

标签:初始化 string int Sale data 构造函数


目录

7.5.1 构造函数初始化值列表

初始化与赋值

观察下面两段构造函数的代码

//初始化bookNo,units_sold,revenue
Sale_data(const String &s, unsigned cnt, double price) :
		 bookNo(s), units_sold(cnt), revenue(cnt*price) {};
//对bookNo,units_sold,revenue赋值
Sale_data(const String &s, unsigned cnt, double price){
    bookNo = s;
    units_sold = cnt;
    revenue = cnt * price;
}
  • 第一种写法是对各成员进行初始化

  • 第二种写法本质上是先对各成员进行默认初始化,再对其赋值

有些时候必须用初始化,而不能用赋值

#include<iostream>
using namespace std;
struct X{
    const int i;
    int &ir;
    //正确:对const int 和 int& 初始化
    X(int ii) : i(ii), ir(ii) {}; 
    
    X(int ii){
        i = ii;  //错误:不能对const int 赋值
        ir = ii; //错误:int &没被初始化
    }
};

如果类成员是const, 引用或其他必须初始化(没有默认构造函数)的类型,那么必须用构造函数初始值列表进行初始化

初始化顺序

初始化的顺序由声明顺序决定,与构造函数初始值列表无关

#include<iostream>
using namespace std;
class X{
public :
    int i;
    int j;
    X(int val = 1) : j(val), i(j) {};
};

int main(){
    X x(1);
    //输出:0 , 1
    cout<<x.i<<" "<<x.j<<endl;
    return 0;
}

X(int val = 1) : j(val), i(j)看似是用val先初始化j,在用j初始化i。

但实际上是先用未定义的j值初始化i,然后用val初始化j

启发:

  1. 构造函数初始值列表的初始化顺序要与声明顺序一致
  2. 避免用成员初始化成员

默认实参和构造函数

下面两段代码等价

//直接手动添加默认构造函数
class X{
public :
    int i;
    X() = default;
    X(int ii) : i(ii) {};
};
//采用默认实参的构造函数可以充当默认构造函数使用
class X{
public :
    int i;
    X(int ii = 0) : i(ii) {};
};

7.5.2 委托构造函数

class Sale_data{
public :
    //非委托的构造函数
    Sale_data(string s, unsigned cnt, double price) :
            bookNo(s), units_sold(cnt), revenue(cnt*price) {}
    //委托的构造函数
    Sale_data() : Sale_data(" ", 0, 0) {}
    Sale_data(string &s) : Sale_data(s, 0, 0) {}
    Sale_data(istream &io) : Sale_data(){
        read(io, *this);
    }
private :
    string bookNo;
    unsigned units_sold;
    double revenue;
};
  • Sale_data()Sale_data(string s)委托给Sale_data(string s, unsigned cnt, double price)
  • Sale_data(istream &io) 委托给Sale_data()Sale_data()再委托给Sale_data(string s, unsigned cnt, double price)

7.5.3 隐式的类类型转换

机制

如果一个构造函数只接受一个参数,那么它实际上定义了一个该参数转换为类类型的隐式转换机制

#include<iostream>
using namespace std;
class X{
public :
    X() = default;
    X(string ss) : s(ss) {}
    //此处的参数必须为const,否则无法接受 常量
    X &combine(const X &y){
        s += y.s;
        return *this;
    }
    string s;
};
int main(){
    X x("hello ");
    string str = "world!";
    //str被隐式转换为X
    x.combine(str);
    //输出 hello world!
    cout<<x.s<<endl;
}

只允许一步类型转换

X.combine("world!")是错误的,因为“world!”先转换为了string,string又转化为X,包含了两步类型转换。

可以显示强制转换

x.combine((string)"world!"); //显式转换为string,隐式转换为X 
x.combine((X)"world !");  //显式转换为X

抑制转换 : explicit

抑制构造函数定义的隐式类型转换:将构造函数声明为explicit

explicit X(string ss) : s(ss) {}

  • explicit只能出现在函数的声明处,不能出现在定义处

  • 不能将explicit构造函数用于拷贝形式的初始化过程P265

    image-20220201132954769

7.5.4 类的静态成员

static关键字声明类的静态成员,它与类直接关联,对所有类的对象可见,被所有对象共享,但不属于任何一个对象。

  • 因为不属于任何一个对象,所以不包含this指针
  • 不能声明为const
  • static关键字只能出现在类内部的声明中,而static函数的定义可内可外
  • static成员的声明周期是整个程序的生命周期

使用

class Account{
public :
    static double rate() {return 3.14;}
    //...
};
  1. 用类名访问double r = Account::rate();

  2. 用类的对象或对象的引用或指针访问

    Account ac1,&ac2;
    Account *ac3 = &ac1;
    r = ac1.rate();
    r = ac2.rate();
    r = ac3->rate();
    

初始化

  • 外部初始化

    class X{
    public :
        //...
        static int m;
    };
    int X::m = 1;
    
  • 内部初始化:constexpr

    class X{
    public :
        //...
        static constexpr int m = 1;
    };
    constint X::m;  //即使在内部初始化一般也得在外部声明一下
    

静态成员可以适用于某些特殊场景

  • 一般成员的类型不能是其所属的类的类型,最多只能是其所属类的类型的指针或引用,而静态成员可以

    image-20220201140531045

  • 静态成员可以作为默认实参image-20220201140614583

标签:初始化,string,int,Sale,data,构造函数
来源: https://www.cnblogs.com/timothy020/p/15914815.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有