0%

C++笔记: 类 (一)

前言

C++是笔者这学期最重要的专业课之一。目前上课内容已简单介绍完C++的类的相关知识。

但是由于老师上课时的解析经常听不懂比较有深度,目前我对于C++类的认识还比较浅显,所以打算再花点时间自学并整理一遍相关内容。

参考书:《C++ Primer Plus》(第6版),《C++程序设计精要教程》(编著 马光志)

类的声明及定义

简介

​ 类即类型的简称,用于描述对象的共同属性和方法。在C++中,类可以使用 structclass 或者 union 来定义。其中,类的属性用数据成员表示,类的方法用函数成员来表示。类的成员可以使用保留字 privatepublic 或者 protected 来标识访问权限。

​ 对象是类的实例,也就是某个类的值,它可以是一个变量,也可以是一个常量。类是一种__数据结构__,而对象代表了一段__内存__,存储了数据结构的值。当产生一个对象时,必须调用__构造函数__初始化对象;当一个对象“死亡”时,则需要调用__析构函数__释放对象占用的资源。

关于访问控制

​ 关键字privatepublicprotected描述了对类成员的访问控制。使用类对象的程序都可以直接访问公有部分,但只能通过公有成员函数 (或者友元函数) 来访问对象的私有成员

private 成员仅供同一类的成员函数访问;protected 成员仅供所在类及派生类的成员函数访问;public 成员可供任何成员或非成员函数访问。

​ 无论类的数据成员还是成员函数,都可以在类的公有部分或者私有部分中声明它。通常把数据成员放在私有部分,组成类接口的成员函数放在公有部分。

​ 不必在class类声明中使用关键字 private ,因为这是它的默认访问控制(注:struct和union定义的类成员默认访问权限为 public)。

1
2
3
4
5
6
7
class world
{
float mass; //默认是私有的
char name[20] //私有
public:
...
};

构造函数

​ 构造函数是类封装的特殊的实例函数成员,用于对对象的数据成员进行初始化,对象必须初始化且仅能初始化一次默认构造函数不能被显式调用。

​ 构造函数为对象申请各种资源用于初始化。除了隐含参数 this 外,构造函数还可以自带若干参数。

​ 构造函数与类名同名。

需要注意的是,如果没有提供任何构造函数,则C++会自动提供默认构造函数,它不会做任何工作。对于某个类,如Stock类,默认构造函数可能如下:

1
Stock::Stock() {...}	//参数表无参

​ 并且,当且仅当没有定义任何构造函数时,编译器才会提供默认构造函数。也就是说,为类定义了构造函数之后,程序员还必须为类提供默认构造函数。如果在定义前者之后未定义后者,以下声明将出错。

1
Stock stock1;

​ 通常用户定义的默认构造函数应可以给给所有成员提供隐式初始值。

​ 构造函数既可以用于类的初始化,也可以用来给类赋新值。

1
2
Stock stock2 = Stock("Boffo Objects", 2, 2.0);	//这里是初始化,可能会创建新的临时对象(看编译器)用于赋值
stock1 = Stock("Niftty Foods", 10, 50.0); //这里是赋值而不是初始化,实际上创建了一个新的对象,然后将其内容复制给stock1

析构函数

​ 析构函数也是类封装的特殊的实例函数成员,其特点是和类名同名且名前带有“ ~ ”,同时,无论是程序自定义还是C++默认生成的析构函数,都只能有一个隐含参数 this 。 析构函数可以被显式调用。

​ 析构函数用于对数据成员申请的资源进行回收,如果构造函数为类成员动态分配了内存(如new),则析构函数相应地要释放这些内存(delete)。与构造函数不同,析构函数可以执行多次,但是应当尽量避免资源被多次释放。

​ 构造函数和析构函数都不可以定义返回类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//示例
struct STRING //定义了一个名为STRING的类
{
typedef char* CHARPTR; //定义类型成员
CHARPTR s; //定义数据成员
int strlen(); //定义函数成员
STRING(const char*); //定义构造函数
~STRING(); //定义析构函数
};

void main()
{
STRING y("complex"); //自动调用构造函数STRING("complex")
}

C++11 列表初始化

​ 在C++11中,可以将列表初始化语法应用于类,只要提供与某个构造函数的参数列表匹配的内容即可。

1
2
Stock hot_tip = {"...", 100, 45.0};	//可与构造函数Stock(const string &co, long n = 0, double pr = 0.0)匹配
Stock temp = {}; //可与无参的默认构造函数Stock()匹配

const成员函数

1
2
const Stock land = Stock("...");
land.show(); //假设show()是Stock的成员函数

​ 假如有如上代码片段,对于当前的C++,编译器会拒绝第二行。因为show()的代码可能不能保证调用对象不被修改——调用对象就跟const一样不应被修改。对于没有任何参数的成员函数,我们并不能通过将函数参数声明为const引用或指向const的指针来解决问题。这里的解决方法是将const关键字加到函数的括号后面,即相关函数的定义和声明应如下所示:

1
2
void show() const;	//保证函数不修改对象
void Stock::show() const;

​ 以这种方式声明和定义的类函数被称为const成员函数

-------------本文结束感谢您的阅读-------------