簡體   English   中英

C++中的循環依賴

[英]Circular Dependency in C++

事實:

  • 我有兩個主要課程:經理和專家。
  • 有幾種不同類型的專家。
  • 專家通常需要其他專家的幫助才能完成工作。
  • 經理認識所有專家,最初每個專家只認識他們的經理。 (這就是問題所在。)
  • 在運行時,管理器創建並存儲專家列表。 然后管理器遍歷列表並要求每個專家進行初始化。 在他們的初始化期間,每個專家要求經理為他們提供滿足某些描述的其他專家。 一旦完成,經理就會進入一個循環,在此期間專家被順序要求執行他們的專業任務。

對我來說,這似乎是一個不錯的模式,但由於經理有專家列表,專家有經理,我遇到了循環依賴問題。

在這種情況下,我應該以某種方式轉發聲明另一個類的存在嗎? (如果是這樣,怎么做?)或者我應該使用一些設計模式來解決這個問題嗎? (如果是什么?)另外...我雖然模式本身很不錯,所以我不介意有人幫助我理解為什么這是一件壞事。

在這兩種情況下,前向聲明另一個類:

經理.h

class Specialist;

class Manager
{
    std::list<Specialist*> m_specialists;
};

專家.h

class Manager;

class Specialist
{
    Manager* m_myManager;
};

唯一需要引入類的頭文件的時候是需要在該類中使用成員函數或變量,或者需要將該類用作值類型等。 當您只需要一個指針或引用時一個類,前向聲明就足夠了。

請注意,前向聲明不僅僅用於解決循環依賴。 您應該盡可能使用前向聲明。 如果完全可行,它們總是比包含額外的頭文件更可取。

這是一個品味問題,但即使沒有循環依賴,前向聲明通常也是頭文件中包含的一個很好的替代方案。 (我不想在這個地方對此進行討論。)所以,這里有一個關於如何為您的問題應用前向聲明的示例:

在 Manager.h 中:

// Forward declaration:
class Specialist;

// Class declaration:
class Manager
{
    // Manager declarations go here.
    // Only pointers or references to
    // the Specialist class are used.
};

在 Manager.cpp 中:

#include "Manager.h"

#include "Specialist.h"

// Manager definitions/implementations
// using the Specialist class go here.
// Full Specialist functionality can be used.

在 Specialist.h 中:

// Forward declaration:
class Manager;

// Class declaration:
class Specialist
{
    // Specialist declarations go here.
    // Only pointers or references to
    // the Manager class are used.
};

在 Specialist.cpp 中:

#include "Specialist.h"

#include "Manager.h"

// Specialist definitions/implementations
// using the Manager class go here.
// Full Manager functionality can be used.

一種選擇是轉發聲明其中一個人,如您所建議的:

struct specialist;

struct manager
{
    std::vector<std::shared_ptr<specialist> > subordinates_;
};

struct specialist
{
    std::weak_ptr<manager> boss_;
};

但是,如果您最終擁有更多的樹狀結構(其中您有多層管理,則person基類也可以工作:

struct person
{
    virtual ~person() { }
    std::weak_ptr<person> boss_;
    std::vector<std::shared_ptr<person> > subordinates_;
};

然后,您可以為層次結構中的不同類型的人派生特定的類。 您是否需要這取決於您打算如何使用這些類。

如果您的實現不支持std::shared_ptr ,它可能支持std::tr1::shared_ptr或者您可以使用boost::shared_ptr

這是正常的東西。 你只需要

class Manager;

在專家標題和

class Specialist; 

在經理標題中

如果您正在使用 shared_ptrs,您可能會發現 shared_from_this 很有用。 (不是為了循環,而是因為聽起來你無論如何都會需要它)

當其他人都在回答核心問題時,我想我會指出這一點。

在運行時,管理器創建並存儲專家列表。 然后管理器遍歷列表並要求每個專家進行初始化。 在他們的初始化期間,每個專家要求經理為他們提供滿足某些描述的其他專家。 一旦完成,經理就會進入一個循環,在此期間專家被順序要求執行他們的專業任務。

我只想指出,這需要一個兩步過程。 如果經理目前只知道一位專家,那么經理如何告訴專家 1 有哪些專家可用於任務 B? 所以你需要:

1) 經理查看專家名單並要求他們表明身份。

2) 經理查看專家名單並詢問他們需要訪問哪些專業,告訴他們誰能滿足他們的要求。

3)經理查看專家名單並告訴他們執行他們的行動。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM