C++类与对象
C++ 类与对象
C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是 C++ 的核心特性,通常被称为用户定义的类型。
类用于指定对象的形式,它包含了数据表示法和用于处理数据的方法。类中的数据和方法称为类的成员。函数在一个类中被称为类的成员。
C++ 类定义
定义一个类,本质上是定义一个数据类型的蓝图。这实际上并没有定义任何数据,但它定义了类的名称意味着它定义了类的对象包括了什么,以及可以在这个对象上执行哪些操作。
类定义是以关键字 class 开头,后跟类的名称。类的主体是包含在一对花括号中。类定义后必须跟着一个分号或一个声明列表。并且其中的成员数据(变量)不能赋初始值。例如,我们使用关键字 class 定义 Box 数据类型,如下所示:
1 | class Box |
类成员的访问限制(权限)
数据封装是面向对象编程的一个重要特点,它防止函数直接访问类类型的内部成员。类成员的访问限制是通过在类主体内部对各个区域标记 public、private、protected 来指定的。关键字 public、private、protected 称为访问修饰符。
一个类可以有多个 public、protected 或 private
标记区域。每个标记区域在下一个标记区域开始之前
或者在遇到类主体结束右括号之前
都是有效的。成员和类的默认访问修饰符是
private。
1 | class Base |
公有(public)成员
公有成员在程序中类的外部是可访问的。您可以不使用任何成员函数来设置和获取公有变量的值。
私有(private)成员
私有成员变量或函数在类的外部是不可访问的,甚至是不可查看的。只有类和友元函数可以访问私有成员。
默认情况下,如果您没有使用任何访问修饰符,类的成员将被假定为私有成员。
保护(protected)成员
保护成员变量或函数与私有成员十分相似,但有一点不同,保护成员在派生类(即子类)中是可访问的。
代码演示:
1 |
|
定义 类 的对象
类提供了对象的蓝图,所以基本上,对象是根据类来创建的。声明类的对象,就像声明基本类型的变量一样。下面的语句声明了类 Box 的两个对象:
Box Box1; // 声明 Box1,类型为 Box Box Box2; // 声明 Box2,类型为 Box
对象 Box1 和 Box2 都有它们各自的数据成员。
访问 对象 里的数据成员
在 类 外访问 类的对象里
的公共数据成员
可以使用直接成员访问运算符 .
来访问。 如使用 “对象名.成员名”
的方式访问public
属性的成员
为了更好地理解这些概念,让我们尝试一下下面的实例:
实例
1 |
|
当上面的代码被编译和执行时,它会产生下列结果:
1 | Box1 的体积:210 |
需要注意的是,私有的成员和受保护的成员不能使用直接成员访问运算符
.
来直接访问。我们将在后续的教程中学习如何访问私有成员和受保护的成员。
类的构造函数
类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。
特点:
- 构造函数的名称与类的名称是完全相同的,
- 并且不会返回任何类型,
- 也不会返回 void。
作用:构造函数可用于为某些成员变量设置初始值。
在创建派生类对象时,构造函数的执行顺序: 基类构造函数 → 对象成员构造函数 → 派生类本身的构造函数
下面的实例有助于更好地理解构造函数的概念:
1 |
|
使用初始化列表来初始化字段
主要是用于 较多参数 时的值的初始化
使用初始化列表来初始化字段:
1 | Line::Line( double len): length(len) |
上面的语法等同于如下语法:
1 | Line::Line( double len) |
假设有一个类 C,具有多个字段 X、Y、Z 等需要进行初始化,同理地,您可以使用上面的语法,只需要在不同的字段使用逗号进行分隔,如下所示:
1 | C::C( double a, double b, double c): X(a), Y(b), Z(c) |
类的析构函数
类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。
析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。
在具有继承关系的类层次体系中,析构函数执行的顺序: 派生类本身的析构函数 → 对象成员析构函数 → 基类析构函数
1 |
|
执行后的结果为:
对象已被创建 Length of line : 6 对象已被删除
类的拷贝构造函数
类的友元函数
类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。 友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。 如果要声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字 friend
1 |
|
类 与 对象详解
到目前为止,我们已经对 C++ 的类和对象有了基本的了解。下面的列表中还列出了其他一些 C++ 类和对象相关的概念,可以点击相应的链接进行学习。
概念 | 描述 |
---|---|
类成员函数 | 类的成员函数是指那些把定义和原型写在类定义内部的函数,就像类定义中的其他变量一样。 |
类访问修饰符 | 类成员可以被定义为 public、private 或 protected。默认情况下是定义为 private。 |
构造函数 与 析构函数 | 类的构造函数是一种特殊的函数,在创建一个新的对象时调用。类的析构函数也是一种特殊的函数,在删除所创建的对象时调用。 |
C++ 拷贝构造函数 | 拷贝构造函数,是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。 |
C++ 友元函数 | 友元函数可以访问类的 private 和 protected 成员。 |
C++ 内联函数 | 通过内联函数,编译器试图在调用函数的地方扩展函数体中的代码。 |
C++ 中的 this 指针 | 每个对象都有一个特殊的指针 this,它指向对象本身。 |
C++ 中指向类的指针 | 指向类的指针方式如同指向结构的指针。实际上,类可以看成是一个带有函数的结构。 |
C++ 类的静态成员 | 类的数据成员和函数成员都可以被声明为静态的。 |
继承 与 派生
单继承
一个类可以派生自多个类,这意味着,它可以从多个基类继承数据和函数。定义一个派生类,我们使用一个类派生列表来指定基类。类派生列表以一个或多个基类命名,形式如下:
1 | class derived_class: access_specifier base_class |
其中,访问修饰符 access_specifier 是
public、protected 或
private 其中的一个,base_class
是之前定义过的某个类(基类)的名称。如果未使用访问修饰符
access_specifier,则默认为 private
。
多继承
多继承即一个子类可以有多个父类,它继承了多个父类的特性。
C++ 类可以从多个类 继承成员,语法如下:
1 | class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,... |
其中,访问修饰符 继承方式 是 public、protected 或 private 其中的一个,用来修饰每个基类,各个基类之间用逗号分隔。
按访问范围分
总结一下三种继承方式:
继承方式 | 基类的public成员 | 基类的protected成员 | 基类的private成员 | 继承引起的访问控制关系变化概括 |
---|---|---|---|---|
public继承 | 仍为public成员 | 仍为protected成员 | 不可访问 | 基类的非私有成员在子类的访问属性不变 |
protected继承 | 变为protected成员 | 仍为protected成员 | 不可访问 | 基类的非私有成员都为子类的保护成员 |
private继承 | 变为private成员 | 变为private成员 | 不可访问 | 基类中的非私有成员都称为子类的私有成员 |
公有继承 pubilc
- 基类的public和protected
成员
的访问属性在派生类中保持不变,但基类的private成员
不可直接访问。 - 派生类中的
成员函数
可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员。 - 通过派生类的
对象
只能访问基类的public成员。
保护继承 protected
- 基类的public和protected
成员
都以protected权限
出现在派生类中,但基类的private成员
不可直接访问。 - 派生类中的
成员函数
可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员。 - 通过派生类的
对象
不能直接访问基类中的任何成员
私有继承 private
- 基类的public和protected
成员
都以private权限
出现在派生类中,但基类的private成员
不可直接访问,且以该派生类
为 基类 的派生类不能访问该基类
的任何成员。 - 派生类中的
成员函数
可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员。 - 通过派生类的
对象
不能直接访问基类中的任何成员。
派生后 继承 到的 权限 所对应的:
派生类的成员
对基类成员的访问
派生类的对象
对基类成员的访问
一个派生类继承了所有的基类方法,但下列情况除外:
- 基类的构造函数、析构函数和拷贝构造函数。
- 基类的重载运算符。
- 基类的友元函数。