数据成员+成员函数
const成员函数:把const关键字放在成员函数的参数列表之后,表示this是一个指向常量的指针。
//即this的默认类型为
Class *const
//加上const之后,变为:
const Class *const
return *this;
一般与类声明(而非定义)在同一个头文件内。
类通过一个或几个特殊的成员函数来控制其对象的初始化过程。
当类没有声明任何构造函数时,编译器才会自动生成默认构造函数。
ClassName() = default; //C++11
如下,冒号及冒号和花括号之间的代码:
Sales_data(const std::string &s, unsigned n, double p) :
bookNo(s), units_sold(n), revenue(p*n) {}
必须指明该构造函数时哪个类的成员。
使用访问说明符(access specifiers)加强类的封装性:
二者的默认访问权限不一样。
当函数时类的接口部分,但它不是类的成员时,无法访问类的私有数据成员。
- 类型成员
- 类的成员的类内初始值
- 可变数据成员
- 内联成员函数
- 从成员函数返回*this
- 如何定义并使用类类型及友元类
class Screen {
public:
typedef std::string::size_type pos;
//等价于:
using pos = std::string::size_type; //二选一即可
private:
pos cursor = 0;
pos height = 0, width = 0;
std::string contents;
};
pos是一个类型成员
1. 可在类的内部把inline作为声明的一部分显式地声明成员函数,
2. 也能在类的外部用inline关键字修饰类的定义。
与非成员函数一样,成员函数也可以被重载。
在变量的声明中加入mutable关键字
- 一个可变数据成员(mutable data member)永远不会是const,即使它是const对象成员。
- 因此,一个const成员函数可以改变一个可变成员的值。
通过区分成员函数是否是const的,可以对其进行重载,类似根据指针参数是否指向const(6.4节)而重载函数。
class Screen {
public:
//根据对象是否是const重载display函数
Screen &display(std::ostream &os)
{ do_display(os); return *this; }
const Screen &display(std::ostream &os) const
{ do_display(os); return *this; }
private:
//该函数负责显示Screen的内容
void do_display(std::ostream &os) const {os << contents;}
//其他成员与之前版本一致
}
当一个成员调用另一个成员时,this指针在其中隐式地传递。
Sales_data item1; //默认初始化Sales_data类型的对象
//可以把类名跟在关键字class或struct后面
class Sales_data item1; //等价声明
可以只声明类而暂时不定义它:
class Screen; //Screen类的声明
类允许包含指向它自身类型的引用或指针。
在类的作用域之外:
普通的数据和函数成员:由对象、引用或者指针使用成员访问运算符来访问。
Screen scr(ht, wd, ' '); //创建Screen对象scr并初始化
Screen *p = &scr;
char c = sca.get(); //访问scr对象的get成员
c = p->get(); //访问p所指对象的get成员
类类型成员:使用作用域运算符访问。
Screen::pos ht = 24, wd = 80; //使用Screen定义的pos类型
定义在类外部的成员:必须同时提供类名和函数名。
class Window_mgr {
public:
//向窗口添加一个Screen,返回它的编号
ScreenIndex addScreen(const Screen&);
//其他成员与之前一致
};
//首先处理返回类型,之后才进入Window_mgr的作用域
Window_mgr::ScreenIndex
Window_mgr::addScreen(const Screen &s)
{
screens.push_back(s);
return screens.size() - 1;
}
C++11新标准:一个委托构造函数使用它所属的类的其他构造函数执行它自己的初始化过程,或者说把它自己的一些(或全部)职责委托给了其他构造函数。
class Sale_data {
public:
Sales_Data(srd::string s, unsigned cnt, double price):
bookNo(s), units_sold(cnt), revenue(cnt*price) { }
//以下为委托构造函数
Salea_data() : Sales_data(" ", 0, 0) { }
Salea_data(srd::string s) : Sales_data(s, 0, 0) { }
Salea_data(srd::istream &is) : Sales_data() { read(is, *this); }
}
string null_book = "9-999-99999-9";
item.combine(null_book);
//构造一个临时的Sales_data对象
//只允许一部累类型转换
item.combine("9-999-99999-9"); //错误!
item.combine(string("9-999-99999-9")); //正确
item.combine(Sales_data("9-999-99999-9")); //正确
为转换显式地使用构造函数
item.combine(Sales_data(null_book));
item.combine(static_cast(cin)); //使用static_cast执行强制转换
类的一些成员与类本身直接相关,而不是与类的各个对象保持关联。
参考:C++Primer第五版