《C++ Primer》读书笔记第七章-1-抽象数据类型 And 访问控制与封装

笔记会持续更新,有错误的地方欢迎指正,谢谢!

这一章是C++ 面向对象的重头戏,以后要转Java/C#的同学这一章要认真地看!
面向对象:把笔这个对象做成一个类,这个类描述了笔的特征,我们可以实例化这个类,从而产生对象(一只只的笔),而笔的使用者不需要关心笔是怎么造出来的,只要会用就好。

类的基本思想是数据抽象和封装:

  1. 数据抽象: 依赖封装。
  2. 封装:实现了 接口和实现的分离。用户只能使用接口而无法访问实现部分。
    接口:用户所能执行的操作。
    实现:包括类的数据成员和函数。

抽象数据类型

设计类的好窍门:你先假装它实现了,去用它,发现需求后,再去实现它。

定义类

1. 成员函数:声明必须在类内部,但定义可在类内或外。
2. this:是指针常量,它只是本身值不变(this是顶层const),但它可以改变它所指对象的值(而如下例子:它所指向的test是常量对象,所以引发了矛盾。)所以不能在常量对象上调用普通成员函数,
例子:

string isbn()
{
    return this->bookNo;//this->可省
}
//我们来试试:
const Sales_data test;//test是常量对象。
test.isbn(); //这里会报错,因为在常量对象上调用了普通成员函数。

常量成员函数:参数列表后带const的函数。如此,便将this声明成了指向常量的指针,使得常量对象可访问常量成员函数,但不可写入新值。
例子:

string isbn() const
{
    return this->bookNo;//this->可省
}
//我们再来试试:
const Sales_data test;//test是常量对象。
test.isbn(); //正确,因为在常量对象上调用了常量成员函数。

总结:(多想想~反正同理于 const+引用 呗)
1. 常量成员函数–>常量和非常量对象都可调用
2. 普通成员函数–>非常量对象才能调用

补充:在类的外面也可以定义其成员函数
我们来定义一下类中声明的avg_price函数,只要在函数名前面加一个作用域说明符::就行了:

double Sales_data::avg_price() const{}

另外,下面我们再来看一下combine函数的定义:

Sales_data& Sales_data::combine(const Sales_data &rhs)
{
    units_sold += rhs.units_sold;
    revenue += rhs.revenue;
    return *this; //返回调用该函数的对象
}

上面的&都是引用,不是取地址。 另外,为什么要这样返回呢?
解释:a.combine(b).combine(c)//a为对象名,1.每次相加都可同时加多项数据;2.为了连续相加呗。

定义类相关的非成员函数

非成员函数:类的设计者常常需要定义一些辅助函数,但它们不属于任何其他的类。
如何判断某函数属于某个类(也就是如何判断一个函数是成员函数):
第一种情况:该函数的定义在该类的大括号内;
第二种情况:该函数的声明在该类的大括号内,而定义(也就是实现)在类外,但实现成员函数时要指明类的名称。
例子:

class A
{
    public:
    void f1(){}; // 这个就是成员函数。
    void f2(); // 这个也是成员函数f2声明,它的实现在类的外部。
};
void A::f2(){} // 这个是成员函数f2的实现。
void f3(){}; // 这个就是非成员函数,它不属于A,也不属于任何其他的类。

构造函数

构造函数的任务是:初始化对象的数据成员,只要类的对象被创建,就会执行构造函数。
注意:构造函数的名字和类名相同且没有返回类型。如果我们的类没有显式地定义构造函数,编译器就会为我们隐式地定义一个默认构造函数。
尽量不用默认构造函数(当然非常简单的类可偷懒用默认初始化),原因如下:

  1. 因为我们自己才知道我们想把数据成员初始化成什么;
  2. 有些成员比如指针默认初始化,值未定义会出问题;
  3. 还有就是类包含类,被包含的那个类没有默认构造函数,那就报错了。

例子:Sales_data(const string &s) : bookNo(s) {}
s是传入参数,s用来初始化成员变量bookNo,这就是个简便写法,等价于:

Sales_data(const string &s)
{
     bookNo = s;
}

拷贝、赋值和析构

我们除了要初始化对象(构造函数),还要控制拷贝、赋值和销毁对象(析构函数)时发生的行为。不过别紧张,现在暂时不学,后面章节学。

访问控制与封装

这个太简单,我就不啰嗦了。就是访问修饰符嘛!
C++中struct和class的区别:struct的默认访问权限是public,class是
private,其他没任何区别。

class A //定义一个struct
{
char c1;
};
A a={'p'}; //报错!!!因为class默认为private,对外不可见。而将class改为struct便可。

因此,struct更适合看成是一个数据结构的实现体,class更适合看成是一个对象的实现体。

友元

那问题来了,Sales_data类的数据成员都是private,那类外面的函数read等函数(也就是 非成员函数)就无法编译了,因为它们无法访问成员变量。
解决方法就是让 非成员函数 跟 类 做朋友:友元
友元:允许其他类或函数访问非公有成员。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值