您的位置:首页 > 编程语言 > C语言/C++

《C++ Primer》读书笔记第七章-3-构造函数再探 And 类的静态成员

2017-09-16 20:29 232 查看
笔记会持续更新,有错误的地方欢迎指正,谢谢!

构造函数再探

构造函数初始值列表

我们初始化 const数据引用类型的数据 的唯一机会就是通过构造函数初始值,于是我们可以这么写:

class ConstRef
{
public:
ConstRef(int value) : i(value), ci(value), ri(i){}
private:
int i;
const int ci;
int &ri;
};


总结:如果成员是const、引用或者属于某种未提供默认构造函数的类类型,我们必须通过构造函数初始值列表为这些成员提供初值。

另外,成员的初始化顺序与它们在类定义中的出现顺序一致,而与初始化列表无关,这句话经常考!

例子:

class X
{
int i;
int j;
public:
X(int val) : j(val), i(j){}//i先被初始化。
};


这样是错的。因为怎么能用未初始化的j去初始化i呢?

最好的方式是用构造函数传进来的参数去初始化成员,这样我们就不用考虑初始化顺序了:
X(int val) : i(val), j(val){}


默认实参和构造函数:

默认构造函数是没有参数的,但我们可以这么干:

class Sales_data
{
public:
Sales_data(string s = "") : bookNo(s){}
}


这是这个类的默认构造函数,它用到了默认实参,这么写的好处是:

不传参数时,也能调用(就相当于默认构造函数,它就用空字符串s去初始化bookNo。)

传参数时,就按照传的来呗。一石二鸟呗,实用哈。

委托构造函数

就是调用 普通的构造函数 帮忙初始化。

默认构造函数的作用

记住一条好习惯:如果定义了其他的构造函数,最好也提供一个默认构造函数,下面来看一个没有默认构造函数的经典错误:

class NoDefault
{
public:
NoDefault(const string &);//定义了构造函数,但没有定义默认构造函数。
};
struct B
{
B(){}
NoDefault b;
//b作为类类型成员,构造函数没有初始化它,于是它会调用默认构造函数初始化,结果该死的NoDefault没有默认构造函数。
};


默认构造对象:使用默认构造函数定义对象的格式为类名+对象名,后面没有空括号,否则就变成了定义函数。

聚合类

此类不常用~

什么样的类是聚合类呢?满足下面四个条件:

1.所有成员都是public;

2.没有定义任何构造函数;

3.没有类内初始值;

4.没有基类,也没有virtual函数;

5.使用花括号初始化;

6.花括号内的初始值顺序与声明顺序一致。

举例:

struct Data
{
int val;
string s;
};
Data a = {0, "temp"}; //实例化,一定要按类内定义的顺序来初始化。


字面值常量类

此类不常用~

不讲了。

类的静态成员

有时候,类需要它的一些成员与类本身直接相关。

例如:银行账户类和利率成员,我们希望利率成员与类直接关联,而不是和银行卡对象关联。也就是,一旦利率成员变化,我们希望所有的银行卡对象都能使用新值。

声明静态成员

static double interestRate;


使用类的静态成员

使用类作用域运算符::直接访问:

double r;
r = Account::rate();


同样可用对象去访问静态成员

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


以上是在类外访问,如果在类内呢?直接访问呗。

定义静态成员

类的静态成员应该在类内声明,类外定义。类成员函数的声明只能放在类内,在类外部定义静态成员时,不能再用static关键字,该关键字只能出现在类内部的声明语句。

我们来定义一个在类内已经声明的static成员:

double Account::interestRate = initRate();


静态数据成员一旦被定义,就一直存在于程序的整个生命周期中。

静态成员的类内初始化

刚刚说过,类的静态成员应该在类外定义,于是C++又来破坏自己定的规矩了。什么狗屁东西,不学了!食之无味弃之可惜。

静态成员能用于某些场景,而普通成员不能

由于静态成员独立于任何对象,所以静态数据成员可以是不完全类型。

不完全类型的特殊情况:静态数据成员可以是它所属的类类型。

而非静态数据成员则受限制,只能声明成它所属类的指针或引用,才可如此用。如下方的
Bar *m2;


class Bar
{
private:
static Bar m1; //这个牛,因为m1是不完全类型的特殊情况。
Bar *m2;//这个也牛,所属类的非静态数据成员的指针 也是不完全类型。
static int &m2; //这个更牛,未初始化的引用。因为m2是不完全类型~

};


因为静态成员一般在外面定义初始化,所以,在类内可以是不完全类型,便可胡作非为。

总结:静态成员的优势:

类内可包含自身类型的静态数据成员,但普通成员只能是指针或引用;

静态成员可以作为默认实参,非静态数据成员的值属于对象的一部分,不能作为默认实参。因为静态成员与类绑定,是类的所有对象来共享的。所以类的对象不同时就用不了咯~(此优势未举例,自己领会哈~)

本章小结:

类允许我们为自己的应用特制类型

类有两项基本能力:

数据抽象,就是定义数据成员和函数成员

封装,保护类的成员不被随意访问(private,友元等)

构造函数可以控制初始化对象的方式

静态成员与类绑定,存在于对象之外,是所有对象来共享的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ c++primer 读书笔记
相关文章推荐