在c ++中转发声明VS编译顺序错误以避免递归头包含

时间:2013-02-14 15:28:17

标签: c++ forward-declaration

我正在处理由很多.h和.c文件组成的c ++中的大型代码。

主要问题是由一对应该相互联系的阶级引起的。 由于软件体系结构中的声明需要,第一个类(名称为A)在“上层”类中初始化。

所以我们得到了类似的东西:

#include A.h
class mainClass{
...
A a;
...
}

A.h看起来像:

#ifndef A_H
#define A_H

#include B.h
class A{
A();
fooA();
...
private:
B b;
...   
}
#endif

A.cpp看起来像:

#include B.h
#include A.h
...
A::A(){
...
b(this) //here I get the first error that follows
...
}
A::fooA(){//do somthing}

为了避免在第二个类中包含相互标题(让它为B),我使用了前向声明和指针变量到A类。

B.h看起来像:

#ifndef B_H
#define B_H

class A; //Forward declaration to A
class B{
B()
B(A* const t)
fooB();
A* a;   //pointer to A object
}

B.cpp看起来像:

#include B.h  

B::B(){
//default constructor. Do Nothing
}
B::B(A* const t){
  this->a=t //constructor that set the pointer to the object of type A
}

B::fooB(){
   a->fooA(); //here i get the second error that follows
}

现在如果在我的Makefile中我在B之前链接A我得到编译错误:

//First error. See code above for line numbers
error: no match for call to ‘(B) (A* const)’

另一方面,如果我在A之前链接B我得到编译错误:

//Second error. see code above for line numbers
error: invalid use of incomplete type ‘struct A’
_B.h:'line of the forward declaration': error: forward declaration of ‘struct A’

我必须管理我对c ++很新,所以我无法理解我错在哪里。

修改

现在我正在使用解决方案:

  1. 使用include guard
  2. 转发声明A类,但不包括B.h
  3. 中的A.h.
  4. 在A.cpp和B.cpp中包括B.h和A.h.在A.h
  5. 之前始终包括B.h.

    但是我得到了同样的错误:

    error: no match for call to ‘(B) (A* const)'

    它可能是构造函数重载问题吗?如果我删除该行

    b(this)

    编译工作正常。

    解决

    如果使用帮助函数在B中设置变量A * a,则使用构造函数在编译期间一切正常。也许我需要更好地理解C ++中的构造函数重载。非常感谢你。

3 个答案:

答案 0 :(得分:0)

尝试在B.cpp中加入“A.h”!

当您需要使用B.cpp中的A时,这将解析您的“A”类型。只要确保你不做任何事情,只要在B.h中保留一个指针/引用A,并在B.cpp中用A做所有实际工作。

答案 1 :(得分:0)

首先 - 遵循'us2012'的想法并使用包含警卫!

然后 - 更改前向声明:

A.H:

#ifndef A_H
#define A_H
class B;
class A{
   A();
   fooA();
   ...
private:
   B b;
   ...   
}
#endif

和A.cpp中包括B.h

在B.h你再次包括A.h - 但包含警卫应该防止错误:

#ifndef B_H
#define B_H

#include "A.h"
class B{
  B()
  B(A* const t)
  fooB();
  A* a;   //pointer to A object
}
#endif

我没有测试过它......但它应该可以工作。

答案 2 :(得分:0)

  1. 使用include guard
  2. 转发声明A类,但不包括B.h
  3. 中的A.h.
  4. 在A.cpp和B.cpp中包括B.h和A.h.在A.h
  5. 之前始终包括B.h.