C++代码重用:继承与组合的比较

 

目录

一、简介

继承

组合

二、继承

三、组合

四、案例说明

4.1一个电子商务系统

4.1.1继承方式

在上述代码中,Order类继承自User类。通过继承,Order类获得了User类的成员函数和成员变量,并且可以添加自己的特性。我们重写了displayInfo()函数,以便在Order类中显示订单相关信息。4.1.2组合方式


一、简介

当涉及到代码重用时,继承和组合是两种常见的机制。下面将更详细地介绍它们的特点、使用方式以及各自的优缺点。

  1. 继承

    • 特点:继承是一种创建新类的方式,通过继承已有类的属性和方法来构建新类。在继承关系中,子类(也称为派生类)继承了父类(也称为基类)的成员变量和成员函数,并且可以添加自己的特性。
    • 使用方式:在C++中,可以使用classstruct关键字定义类,在定义派生类时,使用冒号:指定继承关系。在继承中,派生类可以访问父类的公有成员,但不能访问私有成员。
    • 优点:
      • 代码重用:通过继承可以重用基类的代码,减少重复编写相似代码的工作量。
      • 层次结构:继承可以创建一个层次结构,通过将类组织成父子关系,可以更好地组织和管理代码。
    • 缺点:
      • 紧耦合:继承会在派生类和基类之间创建紧密的依赖关系,如果基类发生变化,可能会影响到所有的派生类。
      • 多继承问题:多继承可能引发命名冲突和复杂性增加的问题,需要小心处理。
  2. 组合

    • 特点:组合是一种通过在一个类中包含另一个类的对象来实现代码重用的机制。在组合关系中,一个类(称为组合类)包含另一个类(称为成员类)的对象作为成员变量,通过调用成员对象的方法来实现自己的功能。
    • 使用方式:在C++中,可以在组合类中声明成员对象作为成员变量,并在组合类的方法中调用成员对象的方法来实现功能。
    • 优点:
      • 松耦合:组合关系比继承关系更加松散,类之间的依赖关系相对较弱,修改一个类不会影响到其他类。
      • 灵活性:组合允许动态地改变成员对象,可以在运行时替换成员对象,提供更大的灵活性。
    • 缺点:
      • 冗余代码:组合可能导致一些重复代码,需要在组合类中转发成员对象的方法。
      • 对象管理:组合类需要负责创建和管理成员对象,增加了额外的工作量。

在选择使用继承还是组合时,需要考虑以下因素:

  • 类的关系:如果存在一种“is-a”的关系,即派生类是基类的一种特殊形式,可以选择使用继承。例如,Dog可以被视为Animal的一种特殊类型。
  • 代码重用程度:如果需要重用大量基类代码,可以选择继承。继承允许派生类直接使用基类的功能,减少了代码编写的工作量。
  • 灵活性要求:如果需要更灵活的类关系和低耦合度,可以选择组合。组合允许动态替换成员对象,提供更大的灵活性。

二、继承

继承是一种通过创建一个新类来继承已有类的属性和方法的机制。在继承关系中,子类(派生类)可以继承父类(基类)的成员变量和成员函数,并且可以添加自己的特性。下面是一个简单的示例:

#include <iostream>class Animal {
public:void eat() {std::cout << "Animal is eating." << std::endl;}
};class Dog : public Animal {
public:void bark() {std::cout << "Dog is barking." << std::endl;}
};int main() {Dog dog;dog.eat();  // 输出 "Animal is eating."dog.bark(); // 输出 "Dog is barking."return 0;
}

在这个示例中,我们定义了一个基类Animal和一个派生类Dog。派生类Dog继承了基类Animaleat方法,并添加了自己的bark方法。通过创建Dog对象,我们可以调用继承的eat方法和派生类自己的bark方法。

优点:

  1. 代码重用:继承允许派生类重用基类的代码,避免了重复编写相似的代码。
  2. 层次结构:继承可以创建一个层次结构,通过将类组织成父子关系,可以更好地组织和管理代码。

缺点:

  1. 紧耦合:继承会在派生类和基类之间创建紧密的依赖关系,如果基类发生变化,可能会影响到所有的派生类。
  2. 多继承问题:多继承可能会引发命名冲突和复杂性增加的问题。

三、组合

组合是一种通过在一个类中包含另一个类的对象来实现代码重用的机制。在组合关系中,一个类(组合类)包含另一个类(成员类)的对象作为成员变量。下面是一个示例:

#include <iostream>class Engine {
public:void start() {std::cout << "Engine is starting." << std::endl;}
};class Car {
private:Engine engine;public:void start() {engine.start();std::cout << "Car is starting." << std::endl;}
};int main() {Car car;car.start(); // 输出 "Engine is starting." 和 "Car is starting."return 0;
}

在这个示例中,我们定义了一个成员类Engine和一个组合类Car。组合类Car包含一个Engine对象作为成员变量,并通过调用Engine对象的方法实现自己的功能。

优点:

  1. 松耦合:组合关系比继承关系更加松散,类之间的依赖关系相对较弱,修改一个类不会影响到其他类。
  2. 灵活性:组合允许动态地改变成员对象,可以在运行时替换成员对象,提供更大的灵活性。

缺点:

  1. 冗余代码:组合可能导致一些重复代码,需要在组合类中转发成员对象的方法。
  2. 对象管理:组合类需要负责创建和管理成员对象,增加了额外的工作量。

结论: 继承和组合都是C++中常用的代码重用机制,它们各有优缺点。在选择使用哪种机制时,需要根据具体的需求和设计要求进行权衡。如果需要创建一个层次结构或者重用大量基类代码,可以选择继承;如果需要更灵活的类关系和低耦合度,可以选择组合。重要的是根据实际情况选择适合的代码重用方式,并结合良好的设计原则来编写高质量的代码。

四、案例说明

4.1一个电子商务系统

其中有两个重要的类:User(用户)和Order(订单)。用户可以下订单,并且一个用户可以有多个订单,因此User类和Order类之间存在一种关系。我们将使用继承和组合两种方式来设计这两个类之间的关系。

4.1.1继承方式

#include <iostream>
#include <string>// 用户类
class User {
private:std::string name;
public:User(const std::string& name) : name(name) {}void setName(const std::string& newName) {name = newName;}std::string getName() const {return name;}virtual void displayInfo() const {std::cout << "User: " << name << std::endl;}
};// 订单类,继承自用户类
class Order : public User {
private:std::string orderId;
public:Order(const std::string& name, const std::string& orderId): User(name), orderId(orderId) {}void setOrderId(const std::string& newOrderId) {orderId = newOrderId;}std::string getOrderId() const {return orderId;}void displayInfo() const override {std::cout << "User: " << getName() << ", OrderId: " << orderId << std::endl;}
};int main() {User user("John");Order order("John", "12345");user.displayInfo();order.displayInfo();return 0;
}

在上述代码中,Order类继承自User类。通过继承,Order类获得了User类的成员函数和成员变量,并且可以添加自己的特性。我们重写了displayInfo()函数,以便在Order类中显示订单相关信息。4.1.2组合方式

#include <iostream>
#include <string>// 用户类
class User {
private:std::string name;
public:User(const std::string& name) : name(name) {}void setName(const std::string& newName) {name = newName;}std::string getName() const {return name;}void displayInfo() const {std::cout << "User: " << name << std::endl;}
};// 订单类,组合了用户类对象
class Order {
private:std::string orderId;User user;
public:Order(const std::string& name, const std::string& orderId): user(name), orderId(orderId) {}void setOrderId(const std::string& newOrderId) {orderId = newOrderId;}std::string getOrderId() const {return orderId;}void displayInfo() const {std::cout << "User: " << user.getName() << ", OrderId: " << orderId << std::endl;}
};int main() {User user("John");Order order("John", "12345");user.displayInfo();order.displayInfo();return 0;
}

在这个例子中,Order类包含了一个User类的对象作为成员变量。通过组合,Order类可以调用User类的方法来处理用户相关的操作。

总结: 在这个案例中,我们展示了继承和组合两种不同的代码重用方式。继承适用于存在"是一种"关系的类,并且可以直接使用基类的成员函数和成员变量。组合适用于存在"有一个"关系的类,其中一个类作为另一个类的成员变量,通过调用成员对象的方法来实现功能。选择使用继承还是组合取决于具体的需求和设计目标,需要权衡各自的优缺点来做出决策。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/344549.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第七讲 单片机驱动彩色液晶屏 控制RA8889软件:显示文字:Part3.自建字库

单片机驱动TFT彩色液晶屏系列讲座 目录 第一讲 单片机最小系统STM32F103C6T6通过RA8889驱动彩色液晶屏播放视频 第二讲 单片机最小系统STM32F103C6T6控制RA8889驱动彩色液晶屏硬件框架 第三讲 单片机驱动彩色液晶屏 控制RA8889软件:如何初始化 第四讲 单片机驱动彩色液晶屏 控…

OpenCV-19图像的仿射变换

放射变换是图像旋转&#xff0c;缩放&#xff0c;平移的总称&#xff0c;具体的做法是通过一个矩阵和原图片坐标进行计算&#xff0c;得到新的坐标&#xff0c;完成变换&#xff0c;所以关键就是这个矩阵。 一、仿射变换之图像平移 使用API------warpAffine&#xff08;src &…

【LangChain学习之旅】—(7) 调用模型:使用OpenAI API还是微调开源Llama2/ChatGLM?

【LangChain学习之旅】—&#xff08;7&#xff09; 调用模型&#xff1a;使用OpenAI API还是微调开源Llama2/ChatGLM&#xff1f; 大语言模型发展史预训练 微调的模式用 HuggingFace 跑开源模型申请使用 Meta 的 Llama2 模型通过 HuggingFace 调用 LlamaLangChain 和 Hugging…

解决:ModuleNotFoundError: No module named ‘dbutils’

解决&#xff1a;ModuleNotFoundError: No module named ‘dbutils’ 文章目录 解决&#xff1a;ModuleNotFoundError: No module named dbutils背景报错问题报错翻译报错位置代码报错原因解决方法方法一&#xff0c;直接安装方法二&#xff0c;手动下载安装方法三&#xff0c;…

强化学习应用(四):基于Q-learning的无人机物流路径规划研究(提供Python代码)

一、Q-learning简介 Q-learning是一种强化学习算法&#xff0c;用于解决基于马尔可夫决策过程&#xff08;MDP&#xff09;的问题。它通过学习一个价值函数来指导智能体在环境中做出决策&#xff0c;以最大化累积奖励。 Q-learning算法的核心思想是通过不断更新一个称为Q值的…

快速搭建前端开发平台利器

JNPF是一款基于springboot、vue.js技术的企业级低代码平台&#xff0c;采用微服务、前后端分离等标准的原生架构&#xff0c;基于可视化业务建模、流程建模、表单建模、报表建模、大屏建模、移动端建模等工具&#xff0c;零代码快速构建业务应用。 官网地址&#xff1a;https:…

C++|44.智能指针

文章目录 智能指针unique_ptr特点一——无法进行复制 shared_ptr特点一——可复制特点二——计数器&#xff08;用于确定删除的时机&#xff09; 其他 智能指针 通常的指针是需要特殊地去申请对应的空间&#xff0c;并在不使用的时候还需要人工去销毁。 而智能指针相对普通的指…

imgaug库指南(19):从入门到精通的【图像增强】之旅

引言 在深度学习和计算机视觉的世界里&#xff0c;数据是模型训练的基石&#xff0c;其质量与数量直接影响着模型的性能。然而&#xff0c;获取大量高质量的标注数据往往需要耗费大量的时间和资源。正因如此&#xff0c;数据增强技术应运而生&#xff0c;成为了解决这一问题的…

SAP OData(三)Query Option

Query option是指客户端在获取EntitySet的URL中后缀的一些指令&#xff0c;在第一篇第四小节我们已经见识了一部分Query指令。在下面表中列出了最重要的QueryOption。注意指令在URL中必须小写。 Operation Query Option Filtering and projecting $filter and $select Sort…

MySQL夯实之路-查询性能优化深入浅出

MySQL调优分析 explain&#xff1b;show status查看服务器状态信息 优化 减少子任务&#xff0c;减少子任务执行次数&#xff0c;减少子任务执行时间&#xff08;优&#xff0c;少&#xff0c;快&#xff09; 查询优化分析方法 1&#xff0e;访问了太多的行和列&#xff1…

react 项目结构配置

1 项目整体目录结构的搭建 如下图&#xff1a; 2 重置css样式: normalize.css reset.less ; 第一步 安装 npm i normalize.css 入口文件index.tsx导入&#xff1a;import ‘noremalize.css’ 第二步 创建自己的css样式&#xff1a;在assets文件夹中创建css…

Salesforce财务状况分析

纵观Salesforce发展史和十几年财报中的信息&#xff0c;Salesforce从中小企业CRM服务的蓝海市场切入&#xff0c;但受限于中小企业的生命周期价值和每用户平均收入小且获客成本和流失率不对等&#xff0c;蓝海同时也是死海。 Salesforce通过收购逐渐补足品牌和产品两块短板&am…