2012-07-09 74 views
3

我遇到了循环依赖项问题,其中包含头文件的顺序很重要。 This问题是类似的,但它没有记录一个类实例化另一个对象的解决方案。在C++模板类中存在循环依赖时包含的修复顺序

问题:

  • 我有两个类:Foo和Bar。酒吧是模板化的。 (Foo可能会或可能不会被模板化)。
  • Foo有一个Bar的实例,Bar有一个Foo类型的指针,Bar的实现需要通过这个指针访问Foo的成员。
  • Foo和Bar必须在单独的文件内执行。由于Bar是模板化的,它的声明和实现必须位于同一个文件中。

在下面的代码中,如果main.cpp在Foo.h之前包含Bar.h,代码将会编译,并且在Bar.h之前包含Foo.h时不会。 有没有办法让代码编译,而不管main.cpp中头文件的顺序?

foo.h中

#ifndef FOO_H 
#define FOO_H 

#include"Bar.h" 
class Foo 
{ 
    public: 
     Bar<> B; 
     void fooStuff(){}; 

}; 
#endif 

Bar.h

#ifndef BAR_H 
#define BAR_H 

class Foo; 
template<int N=0> class Bar 
{ 
    public: 
     Foo * F; 
     void barStuff(); 
}; 

#include"Foo.h" 
template<int N> void Bar<N>::barStuff() 
{ 
     F->fooStuff(); 
}; 
#endif 

的main.cpp

#include"Foo.h" 
#include"Bar.h" 
int main() 
{ 
    Foo F; 
    F.B.barStuff(); 
}; 

回答

2

我需要在Foo之前​​包含Bar,不管它们按照什么顺序包含在main.cpp中。下面的黑客似乎工作:

在Foo.h中,包括Bar.h 外部标头守卫。由于酒吧也有头卫兵,它不会包含多次。

foo.h中

#include"Bar.h" 

#ifndef FOO_H 
#define FOO_H 


class Foo 
{ 
    public: 
     Bar<> B; 
     void fooStuff(){}; 

}; 
#endif 

Bar.h

#ifndef BAR_H 
#define BAR_H 

class Foo; 
template<int N=0> class Bar 
{ 
    public: 
     Foo * F; 
     void barStuff(); 
}; 

#include"Foo.h" 
template<int N> void Bar<N>::barStuff() 
{ 
     F->fooStuff(); 
}; 
#endif 

为主。cpp

#include"Foo.h" 
#include"Bar.h" 
int main() 
{ 
    Foo F; 
    F.B.barStuff(); 
}; 
4

烨s:在Bar之前声明Foo,因为Bar只使用一个指针,它不需要全定义。然后在Bar之后定义Foo - 它使用一个对象,所以它确实需要定义。

class Foo; 

template<int N> class Bar 
{ 
    public: 
     Foo * M; 
     void barStuff(); 
}; 

class Foo 
{ 
    public: 
     Bar<42> B; 
     void fooStuff(){} 
}; 

template<int N> void Bar<N>::barStuff() 
{ 
    M->fooStuff(); 
} 

一般情况下,你需要的任何需要的类的任何属性,如它的大小或成员,只有声明函数,指针或引用时使用的类名的声明的完整定义。

+0

其实,我很确定这只是一个空的声明和完全合法的C++。另一个注意事项(尽管这个错误也存在于OP的代码中)是他似乎对Bar'所用的模板参数有些困惑,并且还有一些专门的缺失。 – Puppy 2012-07-09 11:48:08

+0

@DeadMG:你是对的;出于某种原因,我认为空的声明是非法的,但结果并非如此。这一定是我C日的宿醉。 – 2012-07-09 11:52:12

+0

Foo和Bar需要放在单独的文件中。对不起,我应该早些时候添加这个特定的例子。 – 2012-07-09 12:08:23