Является ли использование двух одинаковых typedefs плохим и как этого избежать? - PullRequest
2 голосов
/ 27 января 2012

Из-за циклических зависимостей вы используете предварительные объявления для некоторых классов:

//B.h
class A;
class B
{
public:
   void foo(A* a);
};
typedef SmartPtr<B> BPtr;

//A.h
class B;
class A
{
public:
   void foo(B* b);
};
typedef SmartPtr<A> APtr;

Теперь, скажем, я хочу изменить прототипы функций для использования умных указателей:

void A::foo(BPtr b);
void B::foo(APtr a);

Очевидно, я не могу форвард объявить APtr или BPtr.Что работает, так это повторное использование typedef:

//B.h
class A;
typedef SmartPtr<A> APtr;
class B
{ 
public:
   void foo(APtr a);
};
typedef SmartPtr<A> APtr;

//A.h
class B;
typedef SmartPtr<B> BPtr;
class A
{ 
public:
   void foo(BPtr b);
};
typedef SmartPtr<A> APtr;

, но я не уверен, что это правильное решение.Есть ли стандартный способ сделать это?Что я сделал не так или опасно?

Ответы [ 3 ]

3 голосов
/ 27 января 2012

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

// defs.h
class A;
class B;
typedef SmartPtr<A> APtr;
typedef SmartPtr<B> BPtr;

//B.h
#include "defs.h"
class B
{
public:
   void foo(APtr a);
};

//A.h
#include "defs.h"
class A
{
public:
   void foo(BPtr b);
};
2 голосов
/ 27 января 2012

Вопрос в основном сводится к тому, является ли этот код в порядке:

#include <memory>

struct A;

typedef std::unique_ptr<A> APtr;

struct A {};

typedef std::unique_ptr<A> APtr;

... где std :: unique_ptr может быть заменен другим классом интеллектуальных указателей.

typedefявляется объявлением, и вы можете иметь столько объявлений, сколько хотите, с одним и тем же именем в одном и том же декларативном регионе, если они объявляют это имя абсолютно одинаковым, например, что-то вроде этого:

extern int i;
extern int i;
extern int i, i, i, i, i, i, i;

В вашем случае они это делают - они оба объявляют APtr как псевдоним для std :: unique_ptr .То, что A является неполным типом в одном объявлении, а полный - в другом, не имеет значения, поскольку для этого объявления полнота A не требуется (и если бы это было так, вы бы получили ошибку компиляции в точке первого определения типа).

Короче говоря: это работает, потому что вы на самом деле не «повторно используете» typedef, вы просто объявляете один и тот же typedef несколько раз, что хорошо.

2 голосов
/ 27 января 2012

Объявляйте умные указатели и форварды классов один раз в общем заголовке и включайте его:

fwd.h:

class A;
class B;
typedef SmartPtr<A> APtr;
typedef SmartPtr<B> BPtr;

Ах:

#include "fwd.h"

struct A {
    void foo(BPtr a);
};
...