关于C++循环依赖问题的理解

2023-05-16

简介

    如果有两个类,类A和类B,A类中有一个B类的对象b作为数据成员,B类中又有一个A类对象a作为数据成员,像这样的情况就叫做循环依赖。那么如何解决类之间的循环依赖问题呢?

代码实例分析

首先看下面这段代码,简单将定义两个类,并把另一个类的对象作为数据成员。

    


class A  

{  

private:  

    B b;  

public:  

    A(){  

        b = new B();  

    }  

    ~A(){  

        delete b;  

    }  

    void test(){  

        cout<<"A"<<endl;  

    }  

}  

class B  

{  

private:  

    A a;  

public:  

    B(){  

        a = new A();  

    }  

    ~B(){  

        delete a;  

    }  

    void test(){  

        cout<<"B"<<endl;  

    }  

}  

看似没有什么问题,但如果点击编译就会出错,根据提示信息可以发现原因是类B未定义却在类A中使用。

解决办法是增加前向引用声明。

在使用一个类之前,必须定义该类;前向引用声明是在引用未定义的类之前,将该类的名字告诉编译器,使编译器知道那是一个类名。但尽管使用了前向引用声明,但是在提供一个完整的类定义之前,不能定义该类的对象,也不能在内联成员函数中使用该类的对象。

那么下一步修改我们的程序,不用对象作为成员变量,改用指针,另外将类A和类B分开。

在a.h文件中


#ifndef A_H  

#define A_H  

  

class B;  

class A  

{  

private:  

    B * b;  

public:  

    B * getB();  

    A();  

    ~A();  

    void doSomething();  

};  

  

#endif // A_H  

  

在b.h文件中


#ifndef B_H  

#define B_H  

  

class A;  

class B  

{  

private:  

    A * a;  

public:  

    setA(A * x) { a=x;}  

    void doSomething();  

    void doSomething2();  

};  

  

#endif // B_H  

  

在a.cpp文件中


#include "a.h"  

#include "b.h"  

  

A::A()  

{  

    b = new B;  

    b->setA(this);  

}  

  

A::~A(){  

    delete b;  

}  

  

B* A::getB()  

{  

    return b;  

}  

  

void A::doSomething()  

{ b->doSomething(); }  

  

在b.cpp文件中


#include <iostream>  

#include "b.h"  

#include "a.h"  

  

using namespace std;  

  

void B::doSomething()  

{ cout<<"OK"<<endl; }  

  

void B::doSomething2()  

{  

    a->doSomething();  

}  

  

最后在main.cpp文件中


#include <iostream>  

#include "a.h"  

#include "b.h"  

  

using namespace std;  

  

int main(int argc, char *argv[])  

{  

    A * a = new A;  

    a->doSomething();  

    B * b = a->getB();  

    b->doSomething2();  

    return 0;  

}  

程序运行结果如图所示


分析:修改代码后,可以看到在a.h中使用了前置引用声明,而在b.h中通过使用include语句来包含类a的定义。在A的构造函数中,对成员b进行了创建操作,而类B的构造函数则使用默认构造函数,并且在主程序中并没有显式地创建一个B类对象,之所以这么做就是为了解决循环依赖问题。

后记

    循环依赖问题是个比较令人头疼的问题,在大型工程中可能由于设计上的失误而经常出现。本篇只是给出一个简单的解决办法。另外还可以通过提取公共信息,将其抽象出来成为一个父类,使两个原本循环依赖的类继承该公共父类,关于这种方法可能用的比较多,大家有兴趣可以自己试一试。希望本篇对大家有所帮助。


  


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于C++循环依赖问题的理解 的相关文章

  • Proxmox VE 多机系统备份

    作者 xff1a 田逸 在我管控的项目里 xff0c 有Proxmox VE集群 xff0c 也有些单独的PVE 我打算把集群上的虚拟机 单机PVE上的虚拟机 xff0c 都备份到同一个大容量存储 这样规划 xff0c 即能有效利用资源 x
  • Proxmox VE 超融合集群实践真传

    第1章 老司机眼中的私有云 3 1 1私有云的定义 3 1 2私有云适用场景 4 1 3私有云行业现状 6 1 4私有云技术要求 xff08 针对Proxmox VE平台 xff09 7 第2章 开源私有云神器Proxmox VE 8 2
  • Proxmox VE 超融合集群创建多个Ceph Pool

    作者 xff1a 田逸 xff08 vx formyz xff09 创建多Ceph Pool的目的 Proxmox VE集群上的虚拟机运行在高速磁盘NVME 而虚拟机附属的数据 xff0c 则指定到低速 廉价 容量大的磁盘空间 为了高可用性
  • Proxmox VE 超融合集群OVS(Open vSwitch)虚拟机网络隔离

    作者 xff1a 田逸 需求的产生 在一个高配置的Proxmox VE 超融合集群中 xff0c 为充分利用资源 xff0c 需要按某种需求将虚拟机之间进行网络隔离 xff0c 以支持更大规模的场景 网络虚拟化基本条件 支持VLAN的网络交
  • 第1章 Rust安装

    Rust是一门安全的语言 xff0c 最近也加入到Linux内核中 xff0c 因此后续这门语言会越来越流行 xff0c 所以准备学习下 xff0c 本篇介绍Rust在Window平台上的安装过程 目录 安装步骤 1 到官网下载安装包 2
  • Proxmox VE 7.0升级到Proxmox VE 7.1虚拟机重启失败

    一单节点pve xff0c 版本为7 0 xff0c 顺手刷了一下更新 xff0c 升级到版本7 1 因为对其中的一个Centos 7虚拟机执行了yum update 重启此虚拟机 xff0c 启动失败 xff0c 尝试多次皆如此 kvm
  • Proxmox VE 修改集群名称

    作者 xff1a 田逸 xff08 formyz Proxmox VE集群一旦创建 xff0c 其集群的名称就固定下来 在Proxmox VE Web管理后台 xff0c 没有相应的菜单或按钮对应与集群名称的修改 xff08 仅仅发现修改虚
  • 第3章 高可用负载均衡集群规划

    作者 xff1a 田逸 xff08 formyz xff09 开篇之初 xff0c 先举几个反例 xff0c 来说明事前规划的重要性 案例一 xff1a 某广告媒体公司 xff0c 需要部署一套媒体播放系统 xff0c 由一台应用服务器和一
  • 《企业级Linux高可用负载均衡集群实践真传》目录

    第1章 关于负载均衡 2 1 1 负载均衡定义 2 1 2 负载均衡在生产环境中的基本要求 3 1 2 1 在线可扩展性 3 1 2 2 高可用性 3 1 2 3 多服务性 4 1 3 负载均衡基本功能 4 1 3 1 负载均衡 4 1 3
  • 4.3 实施部署Nginx 高可用负载均衡集群

    作者 xff1a 田逸 xff08 formyz xff09 部署大致可分为 xff1a 准备工作 配置 验证与交付几个步骤 xff0c 接下来按顺序逐一介绍 4 3 1 准备工作 Nginx高可以负载均衡集群准备工作分两个层面 xff1a
  • xrdp设置开机自启动 update-rc.d xrdp enable

    xrdp设置开机自启动 update rc d xrdp enable
  • FreeRDP 编译和使用介绍

    FreeRDP 编译和使用介绍 FreeRDP是开源的 xff0c 免费的RemoteDesktop Protocol RDP 执行版本 xff0c 它支持多个操作系统平台如Windows xff0c Linux和Android 源代码下载
  • CCF201809-3 元素选择器

    试题编号 xff1a 201809 3试题名称 xff1a 元素选择器时间限制 xff1a 1 0s内存限制 xff1a 256 0MB问题描述 xff1a 版本一 xff08 时间 xff1a 2018 10 23 xff09 xff08
  • CCF201812-4 数据中心

    试题编号 xff1a 201812 4试题名称 xff1a 数据中心时间限制 xff1a 1 0s内存限制 xff1a 512 0MB问题描述 xff1a 样例输入 4 5 1 1 2 3 1 3 4 1 4 5 2 3 8 3 4 2 样
  • R语言一次性更新全部packages

    install packages lib 61 lib lt libPaths 1 pkgs 61 as data frame installed packages lib stringsAsFactors 61 FALSE Package
  • ArchLinux详细安装及配置过程

    总结一下archlinux的安装过程 xff0c 也作为以后安装的参考 xff08 本篇细节内容有待完善 xff0c 目前仅供参考 xff09 可参考archlinux的官方安装教程 xff1a https wiki archlinux o
  • 虚拟机Linux扩容

    查看初始空间 查看分区 扩容 xff1a 1 磁盘分区 root 64 ecs 7837 fdisk dev sda WARNING DOS compatible mode is deprecated It s strongly recom
  • MySQL数据库优化的八种方式(经典必看)

    引言 xff1a 关于数据库优化 xff0c 网上有不少资料和方法 xff0c 但是不少质量参差不齐 xff0c 有些总结的不够到位 xff0c 内容冗杂 偶尔发现了这篇文章 xff0c 总结得很经典 xff0c 文章流量也很大 xff0c
  • .Net Core·寄托于IIS的REST服务405的问题

    Net Core WebAPI寄托于IIS xff0c 使用Put Delete谓词进行访问返回 34 HTTP Error 405 0 Method Not Allowed 34 的错误 IIS7 5中集成了名为 34 WebDAV 34
  • BruteXSS安装和使用

    1 安装Python2 7版本 https www python org downloads windows 使用版本V2 7 13 2 下载BurteXSS https sourceforge net projects brutexss

随机推荐