【C++数据结构】顶层父类的创建与类族结构的进化

2023-11-08 16:20

本文主要是介绍【C++数据结构】顶层父类的创建与类族结构的进化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 前言
  • 一、为什么需要创建顶层父类
  • 二、创建顶层父类Object的意义
  • 三、创建顶层父类Object
    • 3.1 顶层父类接口
    • 3.2 Object具体实现
      • new和delete运算符重载的实现
      • == 和 != 的运算符重载实现
    • 3.3 纯虚析构函数实现
  • 四、类族的结构进化
    • 4.1 怎样进化
    • 4.2 SmartPointer的进化
    • 4.3 Exception类的进化
  • 总结


前言

在C++中,数据结构是编程的重要组成部分,用于组织和管理数据。为了更好地组织代码和实现代码重用,创建一个顶层父类在数据结构中具有重要意义。这个父类可以为不同数据结构提供通用的接口和行为,同时允许具体的数据结构类继承这些通用特性并添加自己特有的功能。本文将介绍如何在C++中创建这样的顶层父类,为不同数据结构的设计和实现提供了框架和结构。


一、为什么需要创建顶层父类

顶层父类的创建

  • 当代软件架构实践中的经验
  • 尽量使用单重继承的方式进行系统设计
  • 尽量保持系统中只存在单一的继承树

不幸的事实:

  • C++ 语言的灵活性使得代码中可以存在多个继承树
  • C++ 编译器的差异使得同样的代码可能表现不同的行为
    new 操作如果失败会发生什么 ?
    在不同的编译器和环境下都会有所差异。
    例如在vs的开发环境下,可以抛出一个exception
    在其他的开发环境下可能是空指针。
    那么这样就不可控,就大大降低我们的可移植性。

所以我们需要一个顶层父类来帮助我们

二、创建顶层父类Object的意义

创建 DbTLib: :0bject 类的意义

  • 遵循经典设计准则,所有数据结构都继承自 Object 类
  • 定义动态内存申请的行为,提高代码的移植性

三、创建顶层父类Object

3.1 顶层父类接口

class Object
{
public:/*throw()不会抛出异常*/void* operator new (size_t size) throw();void operator delete (void* p);void* operator new[](size_t size) throw();void operator delete[](void* p);bool operator == (const Object& obj);bool operator != (const Object& obj);virtual ~Object() = 0;
};

在这里插入图片描述

上面的代码定义了一个名为 Object 的C++类,其中包含了一些特殊的成员函数和声明。下面逐句解释这些代码:

1.class Object:
这一行定义了一个名为 Object 的C++类。这将是一个基类,其他类可以从它派生。
2.public::
这行指示以下成员函数和数据成员在类的公共部分,即可以在类的外部访问。
3.void* operator new (size_t size) throw(); :
这是一个重载的 new 运算符。它用于动态分配内存并返回一个指向该内存的指针。 size_t size 是要分配的内存块的大小。 throw() 关键字表示此运算符不会抛出异常。
4.void operator delete (void* p); :
这是一个重载的 delete 运算符。它用于释放通过 new 分配的内存。参数 void* p 是要释放的内存块的指针。
5.void* operator new[](size_t size) throw(); :
这是重载的数组 new 运算符,用于分配数组形式的内存块,并返回一个指向该内存的指针。 size_t size 指定要分配的内存块的总大小。同样,throw() 表示不会抛出异常。
6.void operator delete[](void* p); :
这是重载的数组 delete 运算符,用于释放通过数组 new 分配的内存。参数 void* p 是要释放的内存块的指针。
7.bool operator == (const Object& obj); :
这是一个自定义的相等运算符重载,用于比较两个 Object 类对象是否相等。
8.bool operator != (const Object& obj); :
这是一个自定义的不等运算符重载,用于比较两个 Object 类对象是否不相等。
9.virtual ~Object() = 0; :
这是 Object 类的虚析构函数。通过在其声明中使用 = 0,它被声明为纯虚函数。这意味着 Object 类是一个抽象基类,不能被实例化,只能用作其他类的基类。任何派生自 Object 的类都必须提供自己的析构函数实现。虚析构函数通常用于确保在派生类中的资源正确释放。

总的来说,这个 Object 类定义了一些特殊的成员函数,使其成为一个抽象基类,为其他类提供了通用的内存分配、释放、比较等功能。其他类可以继承自 Object 类,并实现其纯虚析构函数以添加自己的功能。这种设计通常用于创建一个对象层次结构,其中多个类共享一些通用行为。

3.2 Object具体实现

new和delete运算符重载的实现

我们需要想一下,如何申请空间才是可控的,不会抛出异常的。
当然是我们的malloc函数和free函数啦

所以在外面这个Object里面使用这两个函数来实现我们的运算符重载

void* Object::operator new (size_t size) throw()
{return malloc(size);
}void Object::operator delete (void* p)
{free(p);
}void* Object::operator new[](size_t size) throw()
{return malloc(size);
}void Object::operator delete[](void* p)
{free(p);
}

在这里插入图片描述

== 和 != 的运算符重载实现

我们需要想一下,我们如何去对比本对象和其他对象是否相等呢,很显然,使用值相等是不可能的,因为我们这个Object没有提供任何的flag标识和标识我们这个类是谁

所以我们需要使用一种质朴的方法:比较内存地址,内存地址一样肯定是一样的东西,因为他们指向同一块空间。

bool Object::operator == (const Object& obj)
{return (this == &obj);
}bool Object::operator != (const Object& obj)
{return (this != &obj);
}

在这里插入图片描述

3.3 纯虚析构函数实现

这里的析构并不需要实现具体功能,只需要写个函数体即可

Object::~Object()
{}

四、类族的结构进化

4.1 怎样进化

我们需要写出一个单继承数,如下图:
在这里插入图片描述
我们下面的所有类都要继承Object父类,那么接下来我们就去实现他吧

4.2 SmartPointer的进化

我们直接进行继承即可,不需要改动

template<typename T>
class SmartPointer:public Object
{
protected:T* m_pointer;public:SmartPointer(T* p = nullptr){m_pointer = p;}//.........
};

在这里插入图片描述

4.3 Exception类的进化

和上面一样,我们也只需要进行简单的继承即可:

class Exception:public Object
{
protected:char* m_message;char* m_location;//.............
}

在这里插入图片描述

但是我想各位同学应该发现了一个问题,就是在我们的init函数中申请了空间,没有进行判断是否为空。
那么我们就去改吧:

char sl[16] = { 0 };itoa(line, sl, 10);m_location = static_cast<char*>(malloc(strlen(file) + strlen(sl) + 2));if (m_location != NULL)
{m_location = strcpy(m_location, file);m_location = strcat(m_location, ":");m_location = strcat(m_location, sl);
}

在这里插入图片描述

那么else分支呢,是否需要throw抛出异常呢,其实是不需要的。我们只需要判断是否为空即可,然后进行对应的操作


总结

在C++中,创建顶层父类对于数据结构的设计和实现是非常有益的。它提供了通用的接口和行为,使得代码更易维护和扩展。通过继承和实现,具体的数据结构类可以在保持通用性的同时添加自己特有的功能。这种层次结构的设计有助于提高代码的可重用性和可读性,同时促进了良好的编程实践。希望本文能够帮助你更好地理解如何在C++中创建顶层父类以支持数据结构的设计。

这篇关于【C++数据结构】顶层父类的创建与类族结构的进化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/371047

相关文章

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

Python中顺序结构和循环结构示例代码

《Python中顺序结构和循环结构示例代码》:本文主要介绍Python中的条件语句和循环语句,条件语句用于根据条件执行不同的代码块,循环语句用于重复执行一段代码,文章还详细说明了range函数的使... 目录一、条件语句(1)条件语句的定义(2)条件语句的语法(a)单分支 if(b)双分支 if-else(

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要

Python创建Excel的4种方式小结

《Python创建Excel的4种方式小结》这篇文章主要为大家详细介绍了Python中创建Excel的4种常见方式,文中的示例代码简洁易懂,具有一定的参考价值,感兴趣的小伙伴可以学习一下... 目录库的安装代码1——pandas代码2——openpyxl代码3——xlsxwriterwww.cppcns.c

使用Navicat工具比对两个数据库所有表结构的差异案例详解

《使用Navicat工具比对两个数据库所有表结构的差异案例详解》:本文主要介绍如何使用Navicat工具对比两个数据库test_old和test_new,并生成相应的DDLSQL语句,以便将te... 目录概要案例一、如图两个数据库test_old和test_new进行比较:二、开始比较总结概要公司存在多

c++中std::placeholders的使用方法

《c++中std::placeholders的使用方法》std::placeholders是C++标准库中的一个工具,用于在函数对象绑定时创建占位符,本文就来详细的介绍一下,具有一定的参考价值,感兴... 目录1. 基本概念2. 使用场景3. 示例示例 1:部分参数绑定示例 2:参数重排序4. 注意事项5.