深入了解构造函数

来源:互联网 发布:python turtle安装 编辑:程序博客网 时间:2024/06/11 08:59
struct Sales_data{friend Sales_data add(const Sales_data&, const Sales_data&);friend std::istream &read(std::istream&, Sales_data&);friend std::ostream &print(std::ostream&, const Sales_data&);public://定义构造函数,对类对象进行初始化Sales_data() = default;//默认构造函数,意思是我们需要默认的行为,等同于之前使用的合成默认构造函数Sales_data(const std::string &s) :bookNo(s) {}//冒号以及冒号和花括号之间的代码叫作构造函数初始值列表,负责为新创建的对象的一个或几个数据成员赋初值,每个名字后面跟着用括号扩起来的初始值Sales_data(const std::string &s, unsigned n, double p) :bookNo(s), units_sold(n), revenue(p*n) {}//当某个数据成员被构造函数初始值列表忽略时,他将以与合成默认构造函数相同的方式隐式初始化Sales_data(std::istream &);//类外构造函数的声明,定义在类的外部   //尽管构造函数的参数列表为空,但是由于执行了构造函数体,所以对象的成员仍然能被初始化;通过默认初始化,用类内初始值进行初始化std::string isbn() const{return bookNo;}Sales_data& combine(const Sales_data&);//此为一个引用函数,返回值是一个对象的所有成员值,函数的类型以及返回值类型是 Sales_data& 类型private:double avg_price() const{return units_sold ? revenue / units_sold : 0;}std::string bookNo;unsigned units_sold = 0;double revenue = 0.0;};
//类的外部定义构造函数Sales_data::Sales_data(std::istream &is){read(is, *this);}
//再探构造函数//1.初始化的另外一种方式Sales_data::Sales_data(const string& s, unsigned cnt, double price) {bookNo = s;units_sold = cnt;revenue = cnt * price;}//可能出现的错误class ConstRef{public:ConstRef(int ii);private:int i;const int ci;int& ri;};ConstRef::ConstRef(int ii){i = ii;//ci = ii;error:不能给const赋值//ri = i;error:ri没被初始化}//综上所述,通常情况下都用初始值列表进行初始化,一般不会出错。。。如果成员是const、引用或者属于某种未提供默认构造函数的类类型,务必不能用赋值操作进行初始化//2、成员初始化的顺序class X {int i;int j;public://X(int val): j(val), i(j){};error:理由如下X(int val) :j(val), i(val){}};//成员的初始化顺序与成员在类中定义出现的顺序一致。所以上述程序先初始化i,再初始化j。。。所以程序会出错//但是初始值列表只说明初始化成员的值,而不规定顺序.//所以尽量在构造函数的参数列表中设置好完整的初始值,而不需要使用同一个对象中的不同成员,避免出现上述错误//委托构造函数//class sales_data {public:sales_data(std::string s, unsigned cnt, double price):bookNo(s), units_sold(cnt), revenue(cnt*price){}sales_data():sales_data("", 0, 0){}//此为默认构造函数;<=> sales_data() = default; 这么写意思是委托给三参数的构造函数sales_data(std::string s):sales_data(s,0, 0){}//调用时:<=>sales_data("hello");<=>sales_data("hello", 0, 0);用前者调用,实则用后者初始化sales_data(std::string &is):sales_data(){read(is, *this) }//现委托给了默认构造函数sales_data(),默认函数又将其委托给三参数构造函数,初始化的值从编译器中输入private:std::string bookNo;unsigned units_sold = 0;double revenue = 0.0;};//类的静态成员//class Account {public:void calculate() { amount += amount * interestRate;}static double rate() { return interestRate; }static void rate(double);private:std::string owner;double amount;static double interestRate;static double initRate();};double Account::interestRate = initRate();//对静态成员进行初始化,和全局变量一样,必须出现在任何函数之外//虽然initRate是私有的,但和其他成员的定义是一样的,可以访问类的私有成员。void Account::rate(double newRate){interestRate = newRate;}//若在函数体外定义静态成员函数,则static只能出现在函数体内的声明,定义时不可以再出现static。//类的静态成员存在于任何对象之外,对象中不包含任何与静态数据成员有关的数据。正如例子中所示,静态数据成员被所有的Account对象共享//因此,静态成员函数不与任何对象绑定在一起,也不包含this指针。//所以,静态成员函数不能声明成const的,也不能在static函数体内使用this指针。//静态成员的类内初始化//class account {public:static double rate() { return interestRate; }static void rae(double);private:static constexpr int period = 30;static double interestRate;double daily_tbl[period];};//即使一个常量静态数据成员在类内部被初始化了,通常还得在类的外部定义一下constexpr int account::period;//静态小花园能用于某些场景,而普通成员则不可以class Bar {public://此时Bar还没有定义完全,所以Bar类型是一种不完全类型private:static Bar mem1;Bar *mem2;//Bar mem3;  error:数据成员必须是完全类型};//静态成员的类型可以是他所属的类类型,而非静态数据成员收到限制,只能声明成它所属类的指针或引用//另一个区别是:可以使用静态成员作为默认实参

原创粉丝点击