从现在开始,进入C++ 中面向对象的学习部分。
数据抽象
数据抽象可以帮助我们将对象的具体实现与对象所能执行的操作分离开。我们首先去考虑一个对象应该具有什么样的结构、什么样的功能,而我们又需要对该对象进行如何如何的操作,之后才是对每一个对象进行具体的实体化。
类
类的基本思想便是数据抽象(data abstraction)和封装(encapsulation)。数据抽象依赖于接口(interface)和封装(implementation)。
再进行类的设计时,首先要考虑如何定义抽象数据类型。我们从一个例子来开始进行介绍。
定义抽象数据类型
成员函数(member function)
成员函数即类中将要对对象进行一系列操作的函数,
成员函数的声明必须在类的内部,但是其定义既可以位于类的内部也可以位于类的外部。而作为接口组成部分的非成员函数,其定义和声明都位于类的外部。
对于成员函数,一般的调用方式为:
duixiang.memberfunction();
这说明我们在调用成员函数时,多是针对对象的某一些属性在操作。
类相关的非成员函数
略。给出一段代码以展现IO流作为参数的特殊性(只能被引用,不能被拷贝)
istream &read(istream &is, Sales_data &item)
{
double price=0;
is>>item.bookNo>>item.units_sold>>price;
item.revenue=price*item.units_sold;
return is;
}
构造函数(constructor)
构造函数的任务是初始化类对象的数据成员。
- 构造函数的名字和类型相同。
- 构造函数没有返回类型。
- 构造函数也有一个(可能为空)的参数列表和一个可能为空的函数体。
- 一个类可以有多个构造函数用于重载。
- 如若没有人工写构造函数,系统将会自动写一个构造函数,称为默认构造函数(default constructor)。
- C++11中可以使用‘=default’语句来进行对某一个类的默认构造函数,比如
classname()=default;
下面给出一段例子,来说明构造函数的具体用法:
class Sales_data{
//新增的构造函数
Sale_data()=default;
Sale_data(const std::string &s): bookNo(s) { }
Sale_data(const std::string &s, unsigned n, double p):
bookNo(s), unit_sold(n),revenue(p*n) { }
Sales_data(std::istream &);
//之前已经存在的成员函数
std::string isbn() const{return bookNo;}
Sale_data& conbine(const Sales_data&);
double avg_price() const;
std::string bookNo;
unsigned units_sold=0;
double revenue=0.0;
};
可以看见,在上述代码中出现了两种奇怪的东西:冒号以及冒号和大括号之间的东西。我们新出现的部分称为构造函数初始化列表,他负责对新创建的对象的若干个数据成员进行赋值,不同成员的初始化通过逗号分开。
拷贝、赋值和析构
除了定义类的对象如何进行初始化之外,类还需要控制拷贝、赋值和销毁对象时发生的行为。
- 拷贝:当我们初始化对象,或者以值的方式传递或返回一个对象时。
- 赋值:赋值运算符(=)
- 销毁:一个局部的对象在创建他的块结束时将被销毁,或者比如vecotor对象销毁时存储在其中的对象也会被销毁。
访问控制与封装(public, private)
C++利用访问说明符(access specifiers)加强类的封装性。包括:
- pubilc:该说明符之后的成员在整个程序内可被访问;
- private:该说明符之后的代码只能被该类的成员函数访问。
class与struct的区别:前者默认所有的成员均为private,而后者默认所有的成员均为public
友元(friend)
C++ 允许其他类或者函数去访问他的非公有成员,方法是让那些类或者函数成为它的友元(friend);如果类想把一个函数作为其友元,需要在类内增加一条以friend开头的函数声明语句。
复习到此结束!由于剩下的部分属于第一次C++学习的范畴,所以在此处无法进行笔记!