详细分析C++ 数据封装和数据抽象

我们先来了解一下数据封装和数据抽象的概念。

数据封装是指将实现细节隐藏,仅暴露对外接口,归纳如下:

  • 定义私有成员变量来放置数据,避免外界直接访问该变量
  • 定义公有成员函数来访问私有成员变量,对外暴露接口

数据抽象是指将具体实现细节和概念分离,只呈现出必要的接口,归纳如下:

  • 定义抽象类和纯虚函数来实现数据的抽象,将实际的实现交给子类

具体的实现过程如下:

  1. 定义类与访问控制

首先,我们定义一个类,并使用 publicprivate 关键词对成员变量和成员函数进行访问控制。其中 private 成员变量作为数据存储的载体,需要进行保护,无法直接被外界访问;而 public 成员函数允许外部代码与类进行交互,从而实现对封装的数据进行操作。

class Person
{
private:
  string m_name;
  int m_age;

public:
  void setName(string name) { m_name = name; }
  void setAge(int age) { m_age = age; }
  string getName() { return m_name; }
  int getAge() { return m_age; }
};

上述代码中,我们定义了 Person 类,并包含了两个私有成员变量 m_namem_age,分别用于存储人的姓名和年龄。同时,我们定义了四个公有成员函数:

  • setNamesetAge 用于设置私有成员变量值
  • getNamegetAge 用于获取私有成员变量值

这样做的好处是,我们可以避免外部代码直接访问和操作私有成员变量,从而保证了数据的封装性。

  1. 定义抽象类与纯虚函数

接下来,我们将人员抽象为一个接口,并定义一个抽象类 IPerson。我们在其中定义了一个纯虚函数 virtual void display() = 0;,用于展示人员信息。纯虚函数没有实现语句,要求子类继承并实现它,从而将数据的具体实现委托给子类,实现数据的抽象。

class IPerson
{
public:
  virtual void display() = 0;
};

class Student : public IPerson
{
private:
  string m_name;
  int m_age;
  int m_score;

public:
  Student(string name, int age, int score) : m_name(name), m_age(age), m_score(score) {}

  virtual void display()
  {
    cout << "My name is " << m_name << ", I'm " << m_age << " years old, and my score is " << m_score << endl;
  }
};

class Teacher : public IPerson
{
private:
  string m_name;
  int m_age;
  string m_course;

public:
  Teacher(string name, int age, string course) : m_name(name), m_age(age), m_course(course) {}

  virtual void display()
  {
    cout << "My name is " << m_name << ", I'm " << m_age << " years old, and I teach " << m_course << endl;
  }
};

上述代码中,我们定义了 IPerson 类,并包含一个纯虚函数 display,子类必须继承并实现该函数。接着,我们定义了两个子类 StudentTeacher,它们继承自 IPerson 并实现了 display 函数,以展示学生和老师的信息。这样一来,我们可以将具体实现交给子类,从而实现了数据的抽象。

下面是示例代码的完整实现,可以体验一下:

#include <iostream>

using namespace std;

class Person
{
private:
  string m_name;
  int m_age;

public:
  void setName(string name) { m_name = name; }
  void setAge(int age) { m_age = age; }
  string getName() { return m_name; }
  int getAge() { return m_age; }
};

class IPerson
{
public:
  virtual void display() = 0;
};

class Student : public IPerson
{
private:
  string m_name;
  int m_age;
  int m_score;

public:
  Student(string name, int age, int score) : m_name(name), m_age(age), m_score(score) {}

  virtual void display()
  {
    cout << "My name is " << m_name << ", I'm " << m_age << " years old, and my score is " << m_score << endl;
  }
};

class Teacher : public IPerson
{
private:
  string m_name;
  int m_age;
  string m_course;

public:
  Teacher(string name, int age, string course) : m_name(name), m_age(age), m_course(course) {}

  virtual void display()
  {
    cout << "My name is " << m_name << ", I'm " << m_age << " years old, and I teach " << m_course << endl;
  }
};

int main()
{
  // Example 1: Encapsulation
  Person person;
  person.setName("John");
  person.setAge(30);
  cout << "My name is " << person.getName() << ", I'm " << person.getAge() << " years old" << endl;

  // Example 2: Abstraction
  IPerson* student = new Student("Alex", 20, 90);
  student->display();
  IPerson* teacher = new Teacher("Bob", 40, "Math");
  teacher->display();

  return 0;
}

输出结果为:

My name is John, I'm 30 years old
My name is Alex, I'm 20 years old, and my score is 90
My name is Bob, I'm 40 years old, and I teach Math

可以看到,我们成功地封装了学生和老师的数据,同时实现了数据的抽象。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详细分析C++ 数据封装和数据抽象 - Python技术站

(0)
上一篇 2023年6月25日
下一篇 2023年6月25日

相关文章

  • Swift编程中数组的使用方法指南

    Swift编程中数组的使用方法指南 在Swift编程中,数组是非常常用的数据结构之一。它能够存储同一类型的元素,并且可以根据索引值进行访问和修改。本文将详细讲解Swift编程中数组的使用方法指南。 创建数组 在Swift中,可以使用以下方式来创建一个数组: // 创建一个空数组 var emptyArray: [Int] = [] var anotherEm…

    other 2023年6月25日
    00
  • vant中的toast层级改变操作

    Vant中的Toast层级改变操作攻略 简介 Toast(提示框)是Vant中常用的组件之一,可以用来显示短暂的提示信息。在某些情况下,我们可能需要调整Toast的层级,以确保它在其他浮动元素之上或之下显示。本攻略将详细介绍在Vant中如何改变Toast的层级。 步骤 步骤一:导入Toast组件 首先,确保在代码中正确导入Toast组件,可以使用如下代码进行…

    other 2023年6月28日
    00
  • Android项目基本结构详解

    Android项目基本结构详解攻略 Android项目的基本结构是指项目中各个文件和文件夹的组织方式。了解Android项目的基本结构对于开发者来说非常重要,因为它能够帮助开发者更好地组织和管理项目代码。 1. 项目根目录 项目根目录是Android项目的最顶层目录,它包含了项目的配置文件和一些全局资源。以下是一些常见的文件和文件夹: app文件夹:包含了应…

    other 2023年8月26日
    00
  • 查看连接mysql的IP地址的实例方法

    当你想要查看连接到MySQL数据库的IP地址时,可以按照以下步骤进行操作: 打开MySQL命令行客户端。你可以在终端或命令提示符中输入以下命令来启动MySQL命令行客户端: mysql -u <用户名> -p 其中,<用户名>是你连接MySQL数据库时使用的用户名。按下回车键后,系统会提示你输入密码。 输入密码并按下回车键。如果密码正…

    other 2023年7月31日
    00
  • VS2015 调试 条件和操作设置

    VS2015 调试 条件和操作设置 在 Visual Studio 2015 中,我们可以使用调试器来帮助我们诊断和排除代码中的错误。其中,条件和操作设置可以在我们调试程序时,为我们提供一些额外的控制能力。 条件设置 条件设置可以基于某个表达式的值,来规定是否停止在某处断点或者是继续运行程序到下一个断点。使用条件设置要遵循以下步骤: 右击要设置条件的断点,选…

    其他 2023年3月28日
    00
  • python的sys的append的../

    当然,我可以为您提供有关“python的sys的append的../”的完整攻略,以下是详细说明: 什么是Python的sys的append的../? 在Python中sys.path是一个包含模块搜索路径的列表。当Python解释器在导入模块,会按照sys.path中的路径序搜索模块。sys.path中的路径可以通过sys.path.append()方法进…

    other 2023年5月7日
    00
  • 详解C++之函数重载

    详解C++之函数重载 什么是函数重载? 函数重载(Function Overloading)是指在一个类中定义多个方法,这些方法在名称上是相同的,但参数列表不同,或参数类型不同(或者两者都不同),其目的就是增强程序的灵活性。 函数重载的好处是什么? 函数重载可以让函数名称更易于理解和记忆,也可以减少函数的个数。 重载函数的规则 对于函数重载,需要遵守以下规则…

    other 2023年6月26日
    00
  • DOS 批处理命令For循环命令详解

    DOS 批处理命令For循环命令详解 For 循环命令是DOS批处理中一个重要的命令,它可以在批处理文件中自动进行一些重复的操作。接下来我将详细讲解For循环命令的各种参数以及使用方法。 基本语法 For 循环命令的基本语法如下: for %variable in (set) do command 其中 %variable 代表一个占位符,可以是任意的变量名…

    other 2023年6月26日
    00
合作推广
合作推广
分享本页
返回顶部