C ++: родительский указатель на класс, который включает дочерний - PullRequest
1 голос
/ 17 ноября 2011

У меня есть проблема разработки класса, которая может быть упрощена в этом примере:

// foo.h
#include "foo2.h" 
class foo
{
public:
    foo2 *child;
// foo2 needs to be able to access the instance
// of foo it belongs to from anywhere inside the class
// possibly through a pointer
};

// foo2.h
// cannot include foo.h, that would cause an include loop

class foo2
{
public:
    foo *parent;
// How can I have a foo pointer if foo hasn't been pre-processed yet?
// I know I could use a generic LPVOID pointer and typecast later
// but isn't there a better way?
};

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

Ответы [ 4 ]

9 голосов
/ 17 ноября 2011

Вам не нужно включать файл, если вы используете только указатель, и у вас не будет проблем с зацикливанием, если вы включите их в файлы .cpp:

// foo.h
class foo2; // forward declaration
class foo
{
public:
    foo2 *child;
};

// foo2.h
class foo;
class foo2
{
public:
    foo *parent;
};

//foo.cpp
#include "foo.h"
#include "foo2.h"

//foo2.cpp
#include "foo2.h"
#include "foo.h"

Хотя вам может быть лучше переосмыслить свой дизайн.

3 голосов
/ 17 ноября 2011

Форвардное объявление - друг:

// foo.h
class foo2;

class foo
{
  foo2 *pFoo2;
};

// foo2.h
#include "foo.h"
class foo2
{
  foo *pFoo;
};

Однако, как говорит Пабби, классы, которые должны знать друг о друге, вероятно, должны быть просто одним классом или, возможно, классом с двумя членами, оба изкоторые знают о родительском классе, но не как двусторонние отношения.

Что касается родительства и универсальности:

template  <class Parent>
class  ChildOf
{
public:
  // types
  typedef Parent  ParentType;

  // structors
  explicit ChildOf(Parent& p);
  ~ChildOf();

  // general use
  Parent&  GetParent();
  const Parent&  GetParent() const;

  void  SetParent(Parent& p);

private:
  // data
  Parent  *m_pParent;
};

/*
  implementation
*/
template  <class ParentType>
ChildOf<ParentType>::ChildOf(ParentType& p)
: m_pParent(&p)
{}

template  <class Parent>
ChildOf<Parent>::~ChildOf()
{}

template  <class ParentType>
inline
ParentType&  ChildOf<ParentType>::GetParent()
{
  return *m_pParent;
}

template  <class ParentType>
inline
const ParentType&  ChildOf<ParentType>::GetParent() const
{
  return *m_pParent;
}

template  <class ParentType>
void  ChildOf<ParentType>::SetParent(ParentType& p)
{
  m_pParent = &p;
}
2 голосов
/ 17 ноября 2011

Вы должны использовать предварительные объявления и включать файлы заголовков в ваш cpp

// foo.h
#ifndef FOO_H_
#define FOO_H_
class foo2;

class foo
{
public:
    foo2 *child;
};
#endif

// foo2.h
#ifndef FOO_2_H_
#define FOO_2_H_
class foo;

class foo2
{
public:
    foo *parent;
};
#endif
0 голосов
/ 17 ноября 2011

Используйте предварительное объявление , чтобы сообщить компилятору, что foo2 - это класс, который будет определен впоследствии.

class foo2;

class foo {
    foo2 *child;
};

class foo2 {
    foo *parent;
};
...