一.定义抽象数据类型(类)
1.成员函数:
1).声明和定义:成员函数的声明必须在类的内部,定义可在内部可在外部;非成员函数定义和声明都在类的外部;
2).引入this:(一定有一个对象在调用成员函数)成员函数通过一个隐式参数 this 来访问调用它的对象(this是常量指针,指向对象);
示例一:
Sales_data total;
total.isbn();
当调用 Sales_data 成员函数 isbn 时,编译器将 total 的地址传递给 this,以下是伪代码:
Sales_data::isbn(&total);
示例二:
string isbn() const {
return bookNo;
}
在成员函数内部,可以直接调用对象的成员,相当于:
string isbn() const {
return this->bookNo;
}
3).引入 const 成员函数:const 的作用是修改 this 指针的类型,使 this 成为指向常量的常量指针(默认 this 是指向非常量的常量指针);
默认:Sales_data *const this;
修改后:const Sales_data *const this;
有 const 在参数列表后的成员函数叫常量成员函数,不能改变调用它的对象的内容;
4).类的作用域:编译器先编译成员的声明,再编译成员的函数体,所以使用类中的成员时不必在意次序;
5).在类外部定义成员函数:“ ::” 是作用域运算符;
6).定义返回 this 对象的函数:return *this; 返回调用该函数的对象;
示例:
Sales_data& Sales_data::combine(const Sales_data &rhs; {
a += rhs.a;
b += rhs.b;
return *this;
}
定义一个函数类似某个内置运算符时,应该令该函数的行为模仿此运算符:combine 函数模仿运算符 +=,+= 是左值返回,所以 combine 函数必须返回引用类型 Sales_data&;
2.类相关的非成员函数
1).声明:如果非成员函数是类接口的组成部分,则函数的声明应该与类在同一个头文件内;
2).定义输入输出函数:输入输出函数分别接受一个各自IO类型的引用作为参数(为什么是引用:因为IO类不能被拷贝,只能通过引用来传递它们);
3).定义非成员函数:拷贝类的对象其实是拷贝类的成员,返回值是副本;
示例:
Sales_data sum = lhs;//将 lhs 的数据成员拷贝给 sum
return sum;//返回 sum 的副本
3.构造函数
1).构造函数的作用:每个类都分别定义了它的对象被初始化的方式,构造函数是特殊成员函数,任务是初始化对象的数据成员;
2).合成的默认构造函数:如果没有显式地定义构造函数,编译器会隐式地创建一个合成的默认构造函数,按以下规则初始化:
a.按类内初始值
b.没有类内初始值,= 默认值
3).默认构造函数:人为地使构造函数是默认的;
Salea_data() = default
4).构造函数初始值列表:
Sales_data(const string &s, int n, double p): a(s), b(n), c(p * n) { }
它与以下代码有什么区别?以下代码是类内初始值吗?
Sales_data(const string &s, int n, double p) {
a = s;
b = n;
c = p * n;
}
5).在类的外部定义构造函数
Sales_data::Sales_data(istream &is) {
read(is, *this);//函数作用是从 is 中读取一条信息存入this对象中
}
在调用函数 read 中,使用 *this 将 Sales_data 对象作为实参传递给 read 函数;
4.拷贝、赋值和析构
1).拷贝:
赋值:使用赋值运算符时;
析构:一个局部对象会在创建它的块结束时被销毁,vector 对象(或数组)销毁时储存在其中的对象也会被销毁;
2).合成的拷贝、赋值和析构:未主动定义则编译器会合成这些操作,默认对对象的每个成员执行;
3).某些类不能依赖合成的版本
二.访问控制和封装
1.访问说明符(加强类的封装性):public、private:一个类可以包含零个或多个访问说明符,某个访问说明符可出现多次;
2.class 或 struct 关键字:在第一个访问说明符之前定义的成员,使用 class 关键字是 private 的,使用 struct 关键字是 public 的(唯一区别);
3.友元:允许其他类或者函数访问它的非公有成员
1).友元声明的位置:任意类内位置;
2).友元的声明:友元的声明仅仅指定了访问的权限,所以需要再在类的外部专门对友元函数做一次声明,并且此声明与类放置在同一个头文件内;