《C++多线程编程实战》——1.6 解释继承、重载和覆盖

简介:

本节书摘来自异步社区出版社《C++多线程编程实战》一书中的第1章,第1.6节,作者: 【黑山共和国】Milos Ljumovic(米洛斯 留莫维奇),更多章节内容可以访问云栖社区“异步社区”公众号查看。

1.6 解释继承、重载和覆盖

继承是OOP中非常重要的特性。继承至少关系到两个类(或更多类):如果B类是某一种A类,那么B类的对象就拥有与A类对象相同的属性。除此之外,B类也可以实现新的方法和属性,以代替A类相应的方法和属性。

准备就绪
确定安装并运行了Visual Studio。

操作步骤
现在,执行以下步骤来修改前面的示例。

1.创建一个默认控制台应用程序,命名为InheritanceTest

2.打开InheritanceTest.cpp文件,输入下面的代码:

#include "stdafx.h"
#include <iostream>

using namespace std;

class CPerson
{
public:
   CPerson(int iAge, char* sName)
   {
     this->iAge = iAge;
     strcpy_s(this->sName, 32, sName);
   }
   virtual char* WhoAmI()
   {
     return "I am a person";
   }
private:
   int iAge;
   char sName[32];
};

class CWorker : public CPerson
{
public:
   CWorker(int iAge, char* sName, char* sEmploymentStatus)
     : CPerson(iAge, sName)
   {
     strcpy_s(this->sEmploymentStatus, 32, sEmploymentStatus);
   }
   virtual char* WhoAmI()
   {
     return "I am a worker";
   }
private:
   char sEmploymentStatus[32];
};

class CStudent : public CPerson
{
public:
   CStudent(int iAge, char* sName, char* sStudentIdentityCard)
     : CPerson(iAge, sName)
   {
     strcpy_s(this->sStudentIdentityCard, 32, sStudentIdentityCard);
   }
   virtual char* WhoAmI()
   {
     return "I am a student";
   }
private:
   char sStudentIdentityCard[32];
};

int _tmain(int argc, TCHAR* argv[])
{
   CPerson cPerson(10, "John");
   cout << cPerson.WhoAmI() << endl;

   CWorker cWorker(35, "Mary", "On wacation");
   cout << cWorker.WhoAmI() << endl;

   CStudent cStudent(22, "Sandra", "Phisician");
   cout << cStudent.WhoAmI() << endl;

   return 0;
}```
示例分析
我们创建了一个新的数据类型`CPerson`来表示人。该类型用`iAge`和`sName`作为特征来描述一个人。如果还需要其他数据类型来表示工人或学生,就可以用OOP提供的一个很好的机制——继承来完成。工人首先是人,然后还有一些其他特征,我们用下面的代码把`CPerson`扩展为`CWorker`:

`class CWorker : public CPerson`
也就是说,`CWorker`从`CPerson`类继承而来。`CWorker`类不仅具有基类`CPerson`的所有特征和方法,还有一个对工人而言非常重要的特征`sEmploymentStatus`。接下来,我们还要创建一个学生数据类型。除了年龄和名字,学生也还具有其他特征。同理,我们用下面的代码把`CPerson`扩展为`CStudent`:

`class CStudent : public CPerson`
声明一个对象时,要调用它的构造函数。这里要注意的是:声明一个派生类的对象时,先调用基类的构造函数,后调用派生类的构造函数。如下代码所示:

CWorker( int iAge, char sName, char sEmploymentStatus )
 : CPerson( iAge, sName )
{
  strcpy_s( this->sEmploymentStatus, 32, sEmploymentStatus );
}`
注意看CWorker构造函数的原型,其形参列表后面有一个:(冒号),后面调用的是基类的构造函数,如下代码所示。在创建CPerson时,需要两个参数iAgesName

CPerson(iAge, sName)
调用析构函数的顺序要反过来,即先调用派生类的析构函数,后调用基类的析构函数。

一图胜千言,CPersonCWorkerCStudent类对象分别如图1.2所示。


714c8486e9f6fc1bebecca3beb5ea061dbdd720d

图1.2 CPerson、CWorker和CStudent类对象

可以针对用户自定义的类型来定义运算符的含义,如前面例子中的CComplex。这样做非常好,当cc1c2是复数时,c = c1 + c2比c = ComplexAdd(c1, c2)更直观更容易理解。

要让编译器能处理用户自定义的类型,就必须实现运算符函数或重载相应的函数。假设,有两个矩阵m1m2和一个矩阵表达式m = m1 + m2。编译器知道如何处理基本类型(如,把两个整数相加),但如果事先没有定义CMatrix operator+(const CMatrix& m1, const CMtrix& m2)函数,编译器就不知道如何计算矩阵加法。

覆盖(override)方法也是一种特性,允许派生类在基类已经实现某方法的前提下提供自己的特定实现。如前面例子中的WhoAmI方法所示,其输出如下:

I am a person 
I am a worker 
I am a student```
虽然每个类中的方法名相同,但它们却是不同的方法,有不同的功能。我们可以说,`CPerson`的派生类覆盖了`WhoAmI`方法。

更多讨论
相关文章
|
26天前
|
C++
8. C++继承
8. C++继承
22 0
|
1月前
|
JavaScript 编译器 API
【C++ 函数和过程 进阶篇】全面掌握C++函数返回值:从入门到精通的实战指南
【C++ 函数和过程 进阶篇】全面掌握C++函数返回值:从入门到精通的实战指南
71 1
|
1月前
|
设计模式 存储 uml
C++ 设计模式实战:外观模式和访问者模式的结合使用,派生类访问基类的私有子系统
C++ 设计模式实战:外观模式和访问者模式的结合使用,派生类访问基类的私有子系统
29 1
|
存储 算法 编译器
【C++ 泛型编程 入门篇】C++模板类精讲:探索通用编程的魅力与实战应用
【C++ 泛型编程 入门篇】C++模板类精讲:探索通用编程的魅力与实战应用
65 0
|
1月前
|
安全 算法 编译器
【C++ 泛型编程 入门篇】 C++ 模板元编程之枚举内嵌 实战教程
【C++ 泛型编程 入门篇】 C++ 模板元编程之枚举内嵌 实战教程
55 0
|
13天前
|
存储 算法 Linux
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
37 6
|
30天前
|
存储 算法 编译器
【C++ 内存管理 重载new/delete 运算符 新特性】深入探索C++14 新的/删除的省略(new/delete elision)的原理与应用
【C++ 内存管理 重载new/delete 运算符 新特性】深入探索C++14 新的/删除的省略(new/delete elision)的原理与应用
45 0
|
27天前
|
安全 Java 编译器
C++:继承
C++:继承
30 0
|
29天前
|
算法 C++ 开发者
【C++运算符重载】深入理解C++中的流运算符 >>和<<重载
【C++运算符重载】深入理解C++中的流运算符 >>和<<重载
36 0
|
30天前
|
安全 Java 编译器
C++:继承与派生
C++:继承与派生

热门文章

最新文章