Два класса и встроенные функции

У меня есть два класса, и оба они используют другой класс, например:

// class1.h
class Class1;
#include "class2.h"

class Class1 {
  public:
  static Class2 *C2;
  ...
};

// class2.h
class Class2;
#include "class1.h"

class Class2 {
  public:
  static Class1 *C1;
  ...
};

И когда я определяю его, как в примере выше, он работает (у меня также есть #ifndef, чтобы избежать бесконечного повторения заголовка). Но я также хочу добавить в свои классы несколько встроенных функций. И я прочитал здесь, что мне следует указать определение встроенной функции в файле заголовка, потому что это не сработает, если я помещу их в файл cpp и захочу вызвать их из другого файла cpp (когда я это сделаю, я получаю неопределенную ссылку во время связывания). Но проблема здесь примерно в следующем:

// class1.h
...
inline void Class1::Foo() {
  C2->Bar();
}

Я получаю сообщение об ошибке: недопустимое использование неполного типа «struct Class2».

Так как я могу это сделать?


person klew    schedule 09.02.2010    source источник
comment
Я бы порекомендовал вам пересмотреть свой дизайн. Очень редко бывают ситуации, когда циклические зависимости являются лучшим решением.   -  person David Rodríguez - dribeas    schedule 10.02.2010


Ответы (3)


Вам нужно отложить включение заголовка, но затем включить его и определить свои встроенные методы. Делая это в каждом заголовке, они являются самодостаточными, и включение одного всегда будет включать другое, а включает охранников предотвращая бесконечную рекурсию.

A.hpp

#ifndef INCLUDE_GUARD_B9392DB18D114C1B8DFFF9B6052DBDBD
#define INCLUDE_GUARD_B9392DB18D114C1B8DFFF9B6052DBDBD

struct B;

struct A {
  B* p;
  void foo();
};

#include "B.hpp"

inline
void A::foo() {
  if (p) p->bar();
}

#endif

B.hpp

#ifndef INCLUDE_GUARD_C81A5FEA876A4C6B953D1EB7A88A27C8
#define INCLUDE_GUARD_C81A5FEA876A4C6B953D1EB7A88A27C8

struct A;

struct B {
  A* p;
  void bar();
};

#include "A.hpp"

inline
void B::bar() {
  if (p) p->foo();
}

#endif
person Community    schedule 09.02.2010
comment
Спасибо! Работает отлично! Приятно видеть улучшение скорости примерно на 8%! :) - person klew; 10.02.2010

Вы все перепутали. Вы хотите:

// class1.h
class Class2;

class Class1 {
  public:
  static Class2 *C2;
  ...
};

// class2.h
class Class1;

class Class2 {
  public:
  static Class1 *C1;
  ...
};

И включите соответствующие заголовки в источник. Линия:

class Class1; // or Class2

Объявляет неполный тип, и вы можете иметь указатели и ссылки на неполные типы. Однако после использования он должен быть завершен. Так что просто скажите "эй, это будет существовать!" в шапке, а в источнике расскажите, что это такое.

person GManNickG    schedule 09.02.2010
comment
Спасибо. Я исправил это, но проблема с inline осталась прежней. - person klew; 10.02.2010

Я предлагаю поместить общие методы и члены в базовый класс, а затем унаследовать C1 и C2 от базового класса. Это может исправить проблему циклической зависимости.

person Thomas Matthews    schedule 10.02.2010