7.1 定义抽象数据类型
7.2 访问控制与封装
7.3 类的其他特性
7.4 类的作用域
7.5 构造函数再谈
7.6 类的静态成员
7.1定义抽象数据类型
类的基本思想是数据抽象和封装。数据抽象是一种依赖于接口和实现分离的编程技术。类的接口包括用户所能执行的操作;类的实现则包括类的数据成员,负责接口实现的函数体以及定义类所需的各种私有函数。
封装实现了类的接口和实现的分离。封装后隐藏了它的实现细节,也就是说,类的用户只能使用接口而无法访问实现部分。
类想要实现数据抽象和封装,需要首先定义一个抽象数据类型。
this的引入:
this的目的总是指向”这个"对象,所以this是一个常量指针,我们不允许改变this中保存的地址
class A
{
int function(int para);
}
int A::function(int para) //我们看到的函数定义
{ ...... }
int A::function(A* const this, int para) //编译器的函数定义
{ ...... }
A a;
a.function(100); //我们看到的函数调用
A::function(&a, 100); //编译器的函数调用
const的引入:
可参考我之前写过的:http://blog.youkuaiyun.com/qq_34552886/article/details/70160374
构造函数等可参考我之前写过的:http://blog.youkuaiyun.com/qq_34552886/article/details/70133127
7.2访问控制与封装
使用class或struct关键字:
他们唯一一点的区别是,struct和class的默认访问权限是不太一样的
struct默认访问权限是public,而class默认访问权限是private
友元:http://blog.youkuaiyun.com/qq_34552886/article/details/70245327 ,可参考我之前写的这篇文章
7.4类的作用域
类单独成为一个作用域,同一个作用域的成员(数据或者成员)可以直接访问,而无需在意它们之间声明的先后顺序。这是由编译类代码时编译器的特殊行为决定的:编译器先编译类成员声明,之后再编译成员函数体。对于类外部定义的成员函数:参数列表和函数体内部处在类作用域中,返回值则不处在类作用域中,如果使用需要额外声明。成员函数只能重载成员函数,不能重载类之外的函数,因为作用域不同。类成员函数中变量的查找顺序是:函数内->类内->全局
7.5构造函数再探
不能将构造函数定义为const的,因为在构造函数运行时,这个对象还不存在,也就无法让它获得const属性
构造函数的初始值有时必不可少。如果成员是const或者引用的话,必须将其初始化,随着构造函数体一开始执行,初始化就完成了。我们初始化const或者引用类型的数据成员的唯一机会就是通过构造函数的初始值,必须通过构造函数初始化列表为这些成员提供初值。
class ConstRef{
public:
ConstRef(int ii):i(ii),ci(ii){}
private:
const int i;
int &ci;
};
委托构造函数:
委托构造函数允许构造函数调用同一个类的其他构造函数,该构造函数必须放在构造函数初始化器中
#include <iostream>
using namespace std;
class A
{
private:
int i=5;
string str="初始值";
public:
A(){
str="委托构造函数";
i=99;
}
A(int ii):A(){
//不能写成AA(int ii):A(),i(ii)
//委托构造函数不能再利用初始化器初始化其他数据成员
i=ii;
}
void show(){
cout<<"i="<<i<<",str="<<str<<endl;
}
};
int main()
{
A a(10);
a.show();
}
聚合类
聚合类使得用户可以直接访问其成员,并且具有特殊的初始化语法形式,当一个类满足如下条件时,我们说它是聚合的:
1.所以成员都是public
2.没有定义任何构造函数
3.没有类内初始值
4.没有基类,没有virtual函数
下面就是一个聚合类
struct Data{
int ival;
string s;
};
可以这样初始化: Data val2 ={0,"annil"};
7.6静态成员
可以参考我之前写过的一篇博客:
http://blog.youkuaiyun.com/qq_34552886/article/details/70162183