3

我遇到了一个循环依赖问题,其中包含标题的顺序很重要。这个问题类似,但它没有记录一个类实例化另一个类的对象的解决方案。

问题:

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

在下面的代码中,如果 main.cpp 在 Foo.h 之前包含 Bar.h,则代码编译,而当 Foo.h 在 Bar.h 之前包含时不会编译。有没有一种方法可以编译代码,而不管 main.cpp 中包含的标头的顺序如何?

Foo.h

#ifndef FOO_H
#define FOO_H

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

};
#endif

酒吧.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

主文件

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

2 回答 2

4

是的:Foo之前声明Bar,因为Bar只使用一个指针,它不需要完整的定义。Foo然后在之后定义Bar- 它使用一个对象,因此它确实需要定义。

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();
}

通常,对于需要类的任何属性(例如其大小或成员)的任何内容,您都需要完整定义,并且只需要在声明函数、指针或引用时使用类名的声明。

于 2012-07-09T11:26:09.673 回答
2

我需要在 Foo 之前包含 Bar,无论它们以什么顺序包含在 main.cpp 中。以下黑客似乎有效:

在 Foo.h 中,将 Bar.h 包含在头部防护之外。由于 Bar 也有头守卫,所以它不会被多次包含在内。

Foo.h

#include"Bar.h"

#ifndef FOO_H
#define FOO_H


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

};
#endif

酒吧.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

主文件

#include"Foo.h"
#include"Bar.h"
int main()
{
    Foo F;
    F.B.barStuff();
};
于 2012-07-10T06:50:15.093 回答