第七章:类

一、定义抽象数据类型

1、成员函数的声明必须在类的内部,定义可以内部也可以外部;作为接口组成部分的非成员函数,定义和声明都在外部

  • 如果类函数定义在类内部,则隐式为inline函数
  • 在声明时声明inline,然后在类外定义函数,可以可以构造inline函数
  • inline成员函数应该和类的定义在同一个头文件中

2、this:成员函数通过一个名为this的额外隐式参数来访问调用它的那个对象

Sales_data total;                //实例化total对象
total.isbn();          = Sales_data::isbn(&total)    
//调用类函数时,编译器把total的地址传递给isbn隐式形参this

std::sting isbn() const {return bookNo}        //成员函数内部不需要this可以直接调用
= std::sting isbn() const {return this->bookNo}    //上面的其实是这样调用的
    • 任何类成员的直接访问都被看成是this的隐式引用
    • this是一个常量指针:Sales_data *const:不允许修改隐式this中的地址
Sales_data& Sales_data::combing(const Sales_data &rhs)
{
    ...
    return *this;    //解引用this指针获得执行该函数的对象,即返回totoal的引用
}
  • 返回引用的函数是左值,可以连用:myScreen.move(4,0).set(‘#’);
    • 如果返回不是引用,则连用是通过拷贝副本实现,则上面变成了myScreen.move(4,0);myScreen.set(‘#’);两条语句

3、const成员函数:

std::sting isbn() const {return bookNo}     //const可以修改this的类型为常量类型
从Sales_data * const 变成 const Sales_data* const类型
  • 这样可以在常量对象上使用成员函数:常量对象,常量对象的引用或指针只能调用常量函数
  • 常量成员函数不能改变它调用对象的内容
    • 可以在成员数据前加mutable关键字,做到定义为可变类型,这样就算是在const成员函数依旧可以改变该数据
  • const Screen &dispaly(A) const {return *this}:一个const成员函数如果以引用的形式返回*this,返回类型也得是常量引用

4、定义类相关的非成员函数

  • 这些函数的声明应该与类放在同一个头文件中
  • IO类属于不能拷贝的类型,只能通过引用来传递
  • 执行输出任务的函数应该尽量减少对格式的控制,来确保由用户来决定是否换行
  • 默认情况下,拷贝类的对象其实拷贝的是对象的数据成员

5、构造函数

  • 构造函数的名字与类名相同
  • 构造函数不能声明成const
  • 对于一个普通类必须定义自己的默认构造函数
    • 通过在参数列表后面写上= default来要求编译器生成默认构造函数
  • 通常情况下,构造函数使用类内初始值不失为好的选择
  • 后遭函数不应该轻易覆盖掉类内的初始值
  • 如果成员是const或者引用,必须将其初始化(给默认值或使用构造函数)
  • 最好令构造函数初始值的顺序与成员声明的顺序保持一致
  • 尽量避免使用某些成员初始化其他成员
  • 当一个构造函数委托另一个构造函数时,受委托的构造函数的初始值和函数体依次执行
    • 假如受委托的构造函数体包含有代码的话,先执行这些代码,然后控制权才会交还给委托者的函数体
  • 如果构造函数只接受一个实参,则定义了类类型的隐式转换机制
    • 编译器只会自动执行一步类型转换
    • 关键字explicit支队一个实参的构造函数有效,可以抑制构造函数定义的隐式转换:即只能直接初始化
      • explicit只能出现在类内声明构造函数时,在类外部定义时不应重复

二、访问控制与封装

1、构造函数和部分成员函数紧跟在public说明符后;数据成员和作为实现部分的函数紧跟在private后面

2、使用class和struct定义的唯一区别是默认的访问权限不同

3、友元:在声明开头加一个friend,允许该声明的类或函数访问类的非公有成员

  • 友元不是类的成员,也不受区域访问控制级别的约束
  • 最好在类定义开始或结束前的位置集中声明友元
  • 友元的声明仅仅指明了访问的权限,而非一个普通意义上的函数声明
    • 如果类的用户要使用某个友元函数,必须在友元声明之外再专门对函数进行一次声明
  • 如果一个类指定了友元类,则友元类的成员函数可以访问此类包含非公有成员在内的所有成员
  • 每个类负责控制自己的友元类或友元函数,不存在传递性
  • 对于重载函数声明成友元,不许每个都分别声明
  • 就算在类的内部定义该函数,也必须在类的外部提供相应的声明从而使得函数可见
  • 通常把友元的声明与类本身放在同一个头文件中

三、类的其他特性

1、类型成员:在类内定义自己的类型,类型名通常出现在类开始的地方

2、提供一个类内初始值时,普通数据使用=初始化;其他如类数据使用花括号初始化

四、类的作用域

1、一个类就是一个作用域,类的外部,成员的名字被隐藏起来了

2、成员函数定义在类外部时:

  • 一旦遇到了类名,定义的剩余部分就在类的作用域内了,包括参数列表和函数体
  • 因为函数的返回类型出现在函数名之前,所以返回类型必须指明是哪个类的成员

五、类的静态成员

1、静态成员函数不予任何对象绑定在一起,不包含this指针,也不能声明成const

2、可以直接使用作用域预算符访问静态成员,而无需构建对象

3、既可以在类内部也可以在类外部定义静态成员函数,

  • 当在类外部定义静态成员是,不能重复static关键字,该关键字只出现在类内部
  • 不能在类的内部初始化静态成员,必须在类的外部定义和初始化每个静态成员
  • 一个静态数据成员只能定义一次
  • 一旦被定义,就一直存在程序的整个生命周期中
  • 最好把静态数据成员定义在.cpp文件中

4、静态成员可用的特殊场景

  • 静态数据成员可以使不完全类型
  • 静态数据成员可以就是它所属的类类型
  • 可以用静态成员作为默认实参
posted @ 2015-09-25 15:59  dylqt  阅读(172)  评论(0编辑  收藏  举报