Разработка кода зависимостей иерархии объектов C ++ - PullRequest
4 голосов
/ 22 октября 2011

Я хочу сделать два класса: object и object_manager, но я запутался в том, как они должны видеть / включать друг друга. Я слышал, что для двух заголовков запрещено включать друг друга, и если в моих зависимостях кода есть кружки, то это плохой дизайн кода, и обычно это должно быть похоже на иерархическую структуру (город-> дом-> мебель и мебель не должны знать о существовании города).

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

Это как будто один процесс хочет создать новый процесс, вызывая системные вызовы ОС, поэтому ОС и процесс знают друг о друге.

Есть ли способ, которым я могу реализовать это в правильном дизайне кода или иногда это должно быть плохо ??

Я подумал, что, возможно, у объектов должно быть специальное место, где они будут хранить все свои "системные вызовы", и object_manager будет время от времени проверять его ... но, возможно, есть лучший способ.

Ответы [ 6 ]

1 голос
/ 22 октября 2011

На самом деле это возможно реализовать два.И нет, это не так уж плохо.Вот частичный код.

Допустим, у вас есть файл заголовка

myobject.h

#ifndef _MYOBJECT
#define _MYOBJECT
// Declare the Object Manager class in it.

class MyObjectManager; // forward declaration

class MyObject {
      MyObjectManager manager;
      registerSelf(MyObjectManager &m);
}

#endif _MYOBJECT

Теперь для заголовка ObjectManager

#ifndef _MYOBJECT_MANAGER
#define _MYOBJECT_MANAGER

class MyObject;  // forward declaration

class MyObjectManager {
      private:
                List list[];
      public:
                registerObject(MyObject &o);
};

#endif

Реализация объектного менеджера

#include <myobject>
#include <myobjectmanager>

MyObjectManager::manageMyObject(MyObject &o) {
   list += o; /* etc.  */
}

Реализация объекта

#include <myobject>
#include <myobjectmanager>


MyObject::registerSelf(MyObjectManager &manager) {
     this.manager = manager;
     manager.registerObject(*this);
}
1 голос
/ 22 октября 2011

Использовать предварительную декларацию:

class ObjectManager;

class Object
{
private:
   ObjectManager* m_objManager;
   ....
public:
   ....
};

В файле .cpp вы можете включить ObjectManager.h Также вместо ObjectManager создайте интерфейс, который даст вам больше абстракции для реализации IObjectManager ...

Удачи:).

0 голосов
/ 22 октября 2011

То, что вы описываете, это объект, который может существовать только внутри другого объекта .

Хороший способ реализовать это с помощью вложенных классов:

class object_manager {
  public:
  class object {  // object_manager::object. public allows it to be used outside of manager
    public:
    void foo() {
      object* t = construct(); // can call object_manager methods
    }
  };

  private:
  object my_objects[5]; // can create objects
  static object* construct() { return NULL; }
};

Имейте в виду, что у вас все еще может быть 2 файла cpp для object и object_manager.

0 голосов
/ 22 октября 2011

Во многих случаях классы должны знать друг о друге.Единственная проблема в том, что они должны знать друг о друге частично или, по крайней мере, один класс.Как правило, проблема решается с помощью предварительных объявлений .Единственная проблема в классе A: вы не можете объявить члена, который имеет тип класса B, только указатель или ссылку на класс B.

class B;
class A 
{
   B* oB;

};

class B
{
   A oA;
}:
0 голосов
/ 22 октября 2011

Ниже приведены некоторые общие рекомендации по устранению связи между заголовками:

Вперед Объясните, что вы можете .Иногда ваш класс A использует другие классы (X, Y, ..) только путем передачи ссылок или указателей.Таким образом, в вашем A.h вы можете объявить методы, которые используют эти возвращаемые типы X, Y или типы аргументов, без необходимости компилятору знать полный тип.Это означает, что A.h не нужно включать X.h или Y.h

Использовать идиомы PImpl , иногда лучший способ отделить реализацию от интерфейса (без использования виртуальных или абстрактных классов).) выполняет что-то вроде:


Foo.h

class Foo {
struct Impl;
Impl* m_impl;

public:
Foo();
void SomeMethod();

}

Foo.cpp

#include "X.h"
struct Foo::Impl {
/* actual implementation */
...};

Foo::Foo() : m_impl( new Foo::Impl() ) {};

void Foo::SomeMethod() {
m_impl->SomeMethod();
}
0 голосов
/ 22 октября 2011

Файлы CPP могут включать заголовки друг друга, не вызывая проблемы компиляции (является ли это правильным с точки зрения дизайна, это другой вопрос, но в любом случае это должно быть нормально).Это означает, что они могут вызывать методы друг друга и т. Д.

Что касается файлов header , то заголовок "object manager", скорее всего, будет включать заголовок "object", поскольку класс "object manager"должен работать с экземплярами класса «объект».Если заголовочный файл «object» должен знать о классе «manager объекта», поместите предварительное объявление для «object manager» в заголовочный файл «object».Таким образом, вы можете использовать указатели и ссылки на «менеджер объектов» в заголовочном файле «объекта», не создавая циклическую зависимость включения.

...