Циклическая зависимость, заголовки и шаблоны - PullRequest
1 голос
/ 03 февраля 2011

У меня проблемы с включением модели реализации шаблонов и циклической зависимостью файлов * .h и * .hpp.

Представим себе следующие последовательности наследования классов:

 A->B->C, 
 A->A1,
 B->B1, C->C1

, где A, A1 - абстрактные классы.

Ah (Абстрактный класс)

#ifndef A_H
#define A_H

template <class A>
{
  //some code
  virtual A() = 0;
};

#include "A.hpp"

#endif

A.hpp

#ifndef A_HPP
#define A_HPP
#include "B.h" //Circular dependency
#include "C.h" //Circular dependency

void create Object(A ** a, unsigned int code)
{
  switch (code)
  {
    case 0: *a = new B(); break;
    case 1: *a = new C();

  };
}

#endif

Bh

#ifndef B_H
#define B_H

#include "A.h"

template <class T>
class B : public A <T>
{
  //Some code
};

Ch

#ifndef C_H
#define C_H

#include "C.h"

template <class T>
class C : public B <T>
{
  //Some code
};

A1.h (абстрактный класс)

#ifndef A1_H
#define A1_H

#include "A.h"

template <class T>
class A1 : public A <T>
{
  //Some code
};

#include "A.hpp"

#endif

A1.hpp

#ifndef A1_HPP
#define A1_HPP
#include "B1.h" //Circular dependency
#include "C1.h" //Circular dependency

void create Object(A1 ** a1, unsigned int code)
{
  switch (code)
  {
    case 0: *a = new B1(); break;
    case 1: *a = new C1();

  };
#endif

B1.h

#ifndef B1_H
#define B1_H

#include "B.h"

template <class T>
class B1 : public B <T>
{
  //Some code
};

C1.h

#ifndef C1_H
#define C1_H

#include "C.h"

template <class T>
class C1 : public C <T>
{
  //Some code
};

Как сделать разумное в том числе, чтобы избежать круговой зависимости?Я пытаюсь заменить директивы include на предварительные объявления, но, к сожалению, этого недостаточно для компилятора ...

A.hpp

#ifndef A_HPP
#define A_HPP

template <class T>
class A;
template <class T>
class B;

//some code
#endif

1.hpp

#ifndef A1_HPP
#define A1_HPP

template <class T>
class A;
template <class T>
class B;

//some code
#endif

Ответы [ 3 ]

1 голос
/ 03 февраля 2011

Почему реализация A должна вообще знать о B & C?Если реализация родителя зависит от деталей конкретного потомка, похоже, что наследование используется неправильно.

Вероятно, вы можете просто удалить эти включения и решить проблему таким образом.1007 * Можете ли вы показать нам, почему вам нужно включить B & C в заголовок / реализацию A?

1 голос
/ 03 февраля 2011

Вам потребуется:

  1. Определить каждый класс в своем заголовке
  2. Каждый заголовок должен содержать зависимости, которые ему нужны
  3. Не ** требуется **что зависимость преуспеет в определении класса, а также в объявлении его вперед.

Если вы сделаете все вышеперечисленное, вы позволите другому коду включать заголовки в любом порядке, но они будутдо сих пор работают в своей "круглости".Нет, моя программа проверки орфографии не знала этого слова, поскольку я только что придумал.

Другими словами, вам нужно сделать что-то вроде этого:

foo.h:

  #ifndef FOO_H
  #define FOO_H

  #include "bar.h"

  class bar;       // THIS IS THE CRITICAL LINE

  class foo {
    // ... uses bar
  }
  #endif /* FOO_H */

бар.ч

  #ifndef BAR_H
  #define BAR_H

  #include "foo.h"

  class bar;       // THIS IS THE CRITICAL LINE

  class bar {
    // ... uses foo
  }
  #endif /* BAR_H */
1 голос
/ 03 февраля 2011

A.hpp и A1.h не должны включать ничего, что связано с B или C.

...