C++中的循环依赖

JnB*_*ymn 18 c++ design-patterns circular-dependency

事实:

  • 我有两个主要的课程:经理和专家.
  • 有几种不同类型的专家.
  • 专家通常需要其他专家的帮助才能完成工作.
  • 经理了解所有专家,最初每个专家只知道他们的经理.(这就是问题.)
  • 在运行时,Manager会创建并存储专家列表.然后,Manager迭代列表并要求每个专家进行初始化.在初始化期间,每位专家都要求经理向其提供满足某些描述的其他专家.完成后,管理器将进入循环,在此循环期间,专家被要求按顺序执行其专门任务.

对我而言,这似乎是一个不错的模式,但由于经理有一个专家列表,而专家有一个经理我得到循环依赖问题.

这是一个我应该以某种方式向前宣布一个类存在于另一个类的情况吗?(如果是这样,怎么样?)或者我应该使用一些设计模式来解决这个问题?(如果是这样的话?)另外......我虽然模式本身还不错,所以我不介意有人帮助我理解为什么这是一件坏事.

Pet*_*der 25

在这两种情况下,forward都声明另一个类:

Manager.h

class Specialist;

class Manager
{
    std::list<Specialist*> m_specialists;
};
Run Code Online (Sandbox Code Playgroud)

Specialist.h

class Manager;

class Specialist
{
    Manager* m_myManager;
};
Run Code Online (Sandbox Code Playgroud)

您需要为类引入头文件的唯一时间是您需要在该类中使用成员函数或变量,或者需要将该类用作值类型等.当您只需要指针或引用时一个班级,一个前瞻性声明就足够了.

请注意,前向声明不仅仅用于解决循环依赖性.您应该尽可能使用前向声明.如果它们完全可行,它们总是更好地包括额外的头文件.

  • "他们总是更可取"我非常不同意并且认为他们在任何可以避免的地方都是优选的.在大型中使用前向声明会使代码更难理解,因为跟踪依赖性变得更加困难.此外,当使用现代编译器积极地缓存文件并支持预编译头时,通常很少或没有性能提升.[在一个不相关的说明,你为什么建议`std :: list`?] (5认同)
  • +1 - "前向声明"是关键词 (4认同)
  • 追踪什么依赖?如果前向声明有效,则不再存在依赖性.此外,在任何中途体面的IDE中,跟踪类跟踪作为标题跟踪也同样容易.至于使用`std :: list`,他在OP中说管理器存储了一个专家列表,所以我决定从字面上解释它.我自己可能会使用`vector`,但当然这取决于具体的用例. (3认同)

Fli*_*sch 10

这是一个品味问题,但前向声明通常是包含在头文件中的一个很好的替代品,即使没有循环依赖.(我不想在这个地方就此进行讨论.)所以,这里有一个关于如何为你的问题应用前向声明的例子:

在Manager.h中:

// Forward declaration:
class Specialist;

// Class declaration:
class Manager
{
    // Manager declarations go here.
    // Only pointers or references to
    // the Specialist class are used.
};
Run Code Online (Sandbox Code Playgroud)

在Manager.cpp中:

#include "Specialist.h"

// Manager definitions/implementations
// using the Specialist class go here.
// Full Specialist functionality can be used.
Run Code Online (Sandbox Code Playgroud)

在Specialist.h中:

// Forward declaration:
class Manager;

// Class declaration:
class Specialist
{
    // Specialist declarations go here.
    // Only pointers or references to
    // the Manager class are used.
};
Run Code Online (Sandbox Code Playgroud)

在Specialist.cpp中:

#include "Manager.h"

// Specialist definitions/implementations
// using the Manager class go here.
// Full Manager functionality can be used.
Run Code Online (Sandbox Code Playgroud)