Как передать «this» в качестве аргумента другому конструктору класса без циклических зависимостей? - PullRequest
5 голосов
/ 09 мая 2011

Я имею в виду, в частности, шаблон «Стратегия» (Design Patterns, GoF94), где предполагается, что контекст, передаваемый конструктору стратегии, может быть объектом, который содержит саму стратегию (как член).Но следующее не будет работать:

//analysis.h

class StrategyBase;
class Strategy1;
class Strategy2;
class Analysis
{
   ...
      void ChooseStrategy();
   private:
      StrategyBase* _s;
      ...
};

//analysis.cpp

void Analysis::ChooseStrategy()
{
   if (...) _s = new Strategy1(this);
   else if (...) _s = new Strategy2(this);
   ...
}

//strategy.h

#include analysis.h
...

, а затем StrategyBase и его подклассы получат доступ к элементам данных Analysis.

Это не будет работать, потому что вы не можете создать экземпляр Strategy *классы, прежде чем они были определены.Но его определение зависит от определения анализа.Так как ты должен это сделать?Замените ChooseStrategy на

void SetStrategy(StrategyBase* s) { _s = s; }

и выполните инстанцирование в файлах, которые включают в себя и analysis.h, и Strategy.h?Какая лучшая практика здесь?

Ответы [ 4 ]

6 голосов
/ 09 мая 2011

У вас всегда будут круговые зависимости в шаблоне состояния / стратегии, за исключением очень общих состояний / стратегий.Но вы можете ограничить использование in-size (Lakos) соответствующего другого класса так, чтобы он компилировался, по крайней мере:

  1. Forward-Declare Analysis (analysis.hили strategies.h)
  2. Определить StrategyBase и подклассы (не встроенные методы, которые используют Analysis) (strategies.h)
  3. Определить Analysis (возможно, уже используются встроенные методыкоторые используют стратегии) ​​(analysis.h)
  4. Реализация Analysis и не встроенных методов классов стратегии (analysis.cpp)
3 голосов
/ 09 мая 2011

analysis.cpp также должен включать strategy.h, чтобы подобрать полные определения стратегий.Поскольку это исходный файл, циклическая зависимость отсутствует.

1 голос
/ 09 мая 2011

Вам не нужно создавать экземпляры классов, если вы передаете указатели (или ссылки): используйте прямое объявление .

0 голосов
/ 09 мая 2011

Одна важная особенность c ++, которую иногда довольно сложно выяснить, заключается в том, что классы должны быть предоставлены для компилятора в правильном порядке.И зависимости между классами решают, какой порядок нужно использовать.Это не облегчает то, что люди хотят поместить каждый класс в отдельный файл .h, поэтому порядок классов необходимо указывать несколько раз при определении порядка # include.В то время как люди изучают заголовки и зависимости классов, рекомендуется помещать каждый класс в один и тот же файл .h, так как это заставит вас решить порядок только один раз.После изучения правильного порядка вы можете снова начать использовать хорошие правила размещения всех классов в отдельных заголовочных файлах.

...