标题需要彼此

时间:2012-05-01 07:48:04

标签: c++ class header include dependencies

此问题已被关闭,因为它被视为重复:

  1. C++ cyclical header dependency
  2. cyclic dependency between header files
  3. C++ error: 'Line2' has not been declared
  4. 然而另一个问题与我不同:他们问一个不同的案例,答案不适用于我的问题。他们的回答建议将函数放入.cpp文件中,并在声明之前定义类。我无法将函数放在.cpp中,因为我的类是一个模板,我已经定义了类,但它没用。


    我有两个头文件a.hb.h。在它们中定义了两个模板类AB

    A的函数需要与B的对象一起工作,反之亦然。由于它们是模板类,我不能将该函数放在.cpp文件中,它必须保留在标题中,并且由于包含的顺序而让我头疼。

    解决这个问题的好方法是什么?

    目前我移动函数定义并找到以正确顺序包含标题的方法,但这变得总是更复杂。而且我不喜欢远离类声明的函数定义(例如在其他文件中)。


    示例代码:

    A.H

    #ifndef A_H
    #define A_H
    
    #include <iostream>
    #include "b.h"
    template< typename T > class B;
    
    template< typename T >
    class A {
    public:
        B<void> *b;
        void f();
        void g();
    };
    template< typename T > void A<T>::f() {
        std::cout << "A::f" << std::endl;
        b->f();
    }
    template< typename T > void A<T>::g() {
        std::cout << "A::g" << std::endl;
    }
    
    #endif
    

    b.h

    #ifndef B_H
    #define B_H
    
    #include <iostream>
    #include "a.h"
    template< typename T > class A;
    
    template< typename T >
    class B {
    public:
        A<void> *a;
        void f();
        void g();
    };
    template< typename T > void B<T>::f( ) {
        std::cout << "B::f" << std::endl;
    }
    template< typename T > void B<T>::g( ) {
        std::cout << "B::g" << std::endl;
        a->g();
    }
    
    #endif
    

    的main.cpp

    #include "a.h"
    #include "b.h"
    int main( ) {
        A<void> a;
        B<void> b;
        a.b = &b;
        b.a = &a;
    
        a.f();
        b.g();
    
        return 0;
    }
    

    这不起作用,因为a.h包含b.hb.h然后无法包含a.h,因此B::g是错误。

    对于此示例代码,我可以在B::gmain.cpp的末尾移动a.h,但对于更复杂的程序,这并不容易。

1 个答案:

答案 0 :(得分:1)

实际上,您的代码在我的Visual C ++上按原样编译。原因是编译器在实际调用之前看起来并不是函数“内部”,即在你的情况下直到main.cpp

坦率地说,我不确定这是否符合标准。如果不是,您可以随时将标题拆分为“独立”和“依赖”部分,如下所示:

<强> a_forward.h

#ifndef A_FORWARD_H
#define A_FORWARD_H

template< typename T > class B;

template< typename T >
class A {
public:
    B<T> *b;
    void f();
    void g();
};

#endif

<强> A.H

#ifndef A_H
#define A_H

#include <iostream>
#include "a_forward.h"
#include "b_forward.h"

template< typename T > void A<T>::f() {
    std::cout << "A::f" << std::endl;
    b->f();
}

template< typename T > void A<T>::g() {
    std::cout << "A::g" << std::endl;
}

#endif

<强> b_forward.h

#ifndef B_FORWARD_H
#define B_FORWARD_H

template< typename T > class A;

template< typename T >
class B {
public:
    A<T> *a;
    void f();
    void g();
};

#endif

<强> b.h

#ifndef B_H
#define B_H

#include <iostream>
#include "a_forward.h"
#include "b_forward.h"

template< typename T > void B<T>::f( ) {
    std::cout << "B::f" << std::endl;
}

template< typename T > void B<T>::g( ) {
    std::cout << "B::g" << std::endl;
    a->g();
}

#endif

<强>的main.cpp

---||---