目录
1. 定义抽象数据类型
- 定义在类内部的函数是隐式的inline函数。
- 成员函数通过名为this的额外的隐式参数来访问调用它的那个对象。
this形参是隐式定义的,实际上,任何自定义名为this的参数或变量的行为都是非法的。
this的目的总是指向“这个”对象,因此this是一个常量指针,不允许修改this中保存的地址。 - C++允许把
const关键字
放在成员函数的参数列表之后,此时,紧跟在参数列表后面的const表示 this是一个指向常量的指针。这样使用const的成员函数被称作常量成员函数。
这样的函数不能改变调用它的对象的内容。
常量对象、常量对象的指针或引用都只能调用常量成员函数。
std::string isbn() const {return bookNo;}
- 当我们定义的函数类似于某种内置运算时,应该令该函数的行为尽量模仿这个运算符。
内置的运算符把左侧运算对象当成左值返回。
return *this;
-
类相关的非成员函数
非成员函数通常把函数的声明和定义分离开,如果函数在概念上属于类但是不定义在类内,则它一般应与类的声明在一个头文件。 -
构造函数不能被声明为const的
-
默认构造函数 (合成的默认构造函数)
- 如果存在类内的初始值,用它来初始化成员
- 否则,默认初始化该成员。
-
=default 的含义
[C++11新标准] 要求编译器生成构造函数。
当我们已经定义了一个构造函数,又需要编译器为我们合成默认构造函数时。
如果=default在类内,则默认构造函数是inline;
如果在类外,则其默认情况下不是inline。 -
构造函数初始值列表
Sale_data(const std::string &s,unsigned n,double p):
bookNo(s), units_sold(n), revenue(p *n){ }
sale_data::sale_data(std::istream &is)
{
read(is,*this);//从is中读取一条信息存入this对象
}
2. 访问控制与封装
2.1 struct与class的区别
如果使用struct关键字,则定义在第一个访问说明符之前的成员是public;相反,对于class关键字,这些成员是private。
因此,出于统一编程风格的考虑,当我们希望定义的类的所有成员是public时,使用struct;反之,使用class。
class 与struct定义类的唯一区别就是默认的访问权限。
2.2 友元 friend
- 类可以允许其他类或函数访问它的private成员,声明其他类或函数为其友元 。
在类的定义中,增加一条以friend为开头的函数声明语句。
友元声明只能出现在类定义的内部。
一般来说,最好在类定义开始或结束前的位置集中声明友元。
友元声明仅指定了访问的权限,如需要调用某个友元函数,需要在专门对函数进行一次声明。通常把该声明与类放在同一个头文件。 - 友元类
友元类的成员函数可以访问此类的所有成员。
class screen{
friend class window_mgr;
};
友元关系不存在传递性。 class A的友元类的友元,不具有访问A private的权限。
- 友元 成员函数
class Screen {
friend void Windows_mgr::clear(ScreenIndex);
};
- 对于重载函数的友元声明,需要对这组函数的每一个分别声明。
3. 类的其他特性
3.1 定义一个类型成员
class Screen{
public:
typedef std::string::size_type pos;
private:
pos cursor = 0;
pos height = 0, width = 0;
std::string contents;
}
可以等价使用类型别名:
class screen{
public:
using pos = std::string::size_type;
}
类型成员通常出现在类开始的地方,必须先定义后使用。
3.2 可变数据成员
mutable关键字
- 一个mutable成员永远不会是const,即使它是const对象的成员。因此,一个const成员函数可以改变一个可变成员的值。
class screen {
public:
void some_member() const; //const 成员函数
provate:
mutable size_t access_ctr;
};
void screen::some_member() const
{
++access_ctr; //可以改便mutable的值
}
3.3 委托构造函数
[C++11]
委托构造函数使用它所属类的其他构造函数执行它自己的初始化过程。其成员初始值列表只有一个唯一的入口,就是类名本身。
- 类内初始值,必须以符号=或者花括号来表示。
- 一个const成员函数如果以引用的形式返回*this,那么它的返回类型将是常量引用。
- 编译器处理完类中的全部声明后,才会处理成员函数的定义。
- 如果在类中,成员使用了外层作用域中的某个名字,而该名字代表一种类型,则类不能在之后重新定义该名字。
- 如果成员是const、引用,或者属于某种未提供默认构造函数的类类型,我们必须通过构造函数初始值列表为这些成员提供初值。成员的初始化顺序与它们在类定义中出现的顺序一致,与初始值列表的顺序无关。(最好使上述两者顺序保持一致)
- 如果一个构造函数为所有参数都提供了默认实参,则其实际上也定义了默认构造函数。
class sale_data{
public :
sale_data(std::string s = " " ):bookNo(s){ }
};