前言
C++是笔者这学期最重要的专业课之一。目前上课内容已简单介绍完C++的类的相关知识。
但是由于老师上课时的解析
经常听不懂比较有深度,目前我对于C++类的认识还比较浅显,所以打算再花点时间自学并整理一遍相关内容。参考书:《C++ Primer Plus》(第6版),《C++程序设计精要教程》(编著 马光志)
类的声明及定义
简介
类即类型的简称,用于描述对象的共同属性和方法。在C++中,类可以使用 struct
、class
或者 union
来定义。其中,类的属性用数据成员表示,类的方法用函数成员来表示。类的成员可以使用保留字 private
、public
或者 protected
来标识访问权限。
对象是类的实例,也就是某个类的值,它可以是一个变量,也可以是一个常量。类是一种__数据结构__,而对象代表了一段__内存__,存储了数据结构的值。当产生一个对象时,必须调用__构造函数__初始化对象;当一个对象“死亡”时,则需要调用__析构函数__释放对象占用的资源。
关于访问控制
关键字private
、public
和 protected
描述了对类成员的访问控制。使用类对象的程序都可以直接访问公有部分,但只能通过公有成员函数 (或者友元函数) 来访问对象的私有成员。
private
成员仅供同一类的成员函数访问;protected
成员仅供所在类及派生类的成员函数访问;public
成员可供任何成员或非成员函数访问。
无论类的数据成员还是成员函数,都可以在类的公有部分或者私有部分中声明它。通常把数据成员放在私有部分,组成类接口的成员函数放在公有部分。
不必在class类声明中使用关键字 private
,因为这是它的默认访问控制(注:struct和union定义的类成员默认访问权限为 public
)。
1 | class world |
构造函数
构造函数是类封装的特殊的实例函数成员,用于对对象的数据成员进行初始化,对象必须初始化且仅能初始化一次。 默认构造函数不能被显式调用。
构造函数为对象申请各种资源用于初始化。除了隐含参数 this
外,构造函数还可以自带若干参数。
构造函数与类名同名。
需要注意的是,如果没有提供任何构造函数,则C++会自动提供默认构造函数,它不会做任何工作。对于某个类,如Stock类,默认构造函数可能如下:
1 | Stock::Stock() {...} //参数表无参 |
并且,当且仅当没有定义任何构造函数时,编译器才会提供默认构造函数。也就是说,为类定义了构造函数之后,程序员还必须为类提供默认构造函数。如果在定义前者之后未定义后者,以下声明将出错。
1 | Stock stock1; |
通常用户定义的默认构造函数应可以给给所有成员提供隐式初始值。
构造函数既可以用于类的初始化,也可以用来给类赋新值。
1 | Stock stock2 = Stock("Boffo Objects", 2, 2.0); //这里是初始化,可能会创建新的临时对象(看编译器)用于赋值 |
析构函数
析构函数也是类封装的特殊的实例函数成员,其特点是和类名同名且名前带有“ ~ ”,同时,无论是程序自定义还是C++默认生成的析构函数,都只能有一个隐含参数 this
。 析构函数可以被显式调用。
析构函数用于对数据成员申请的资源进行回收,如果构造函数为类成员动态分配了内存(如new),则析构函数相应地要释放这些内存(delete)。与构造函数不同,析构函数可以执行多次,但是应当尽量避免资源被多次释放。
构造函数和析构函数都不可以定义返回类型。
1 | //示例 |
C++11 列表初始化
在C++11中,可以将列表初始化语法应用于类,只要提供与某个构造函数的参数列表匹配的内容即可。
1 | Stock hot_tip = {"...", 100, 45.0}; //可与构造函数Stock(const string &co, long n = 0, double pr = 0.0)匹配 |
const成员函数
1 | const Stock land = Stock("..."); |
假如有如上代码片段,对于当前的C++,编译器会拒绝第二行。因为show()的代码可能不能保证调用对象不被修改——调用对象就跟const一样不应被修改。对于没有任何参数的成员函数,我们并不能通过将函数参数声明为const引用或指向const的指针来解决问题。这里的解决方法是将const关键字加到函数的括号后面,即相关函数的定义和声明应如下所示:
1 | void show() const; //保证函数不修改对象 |
以这种方式声明和定义的类函数被称为const成员函数。