如何在没有循环的情况下将实现移动到多个头文件?

时间:2015-06-11 15:49:25

标签: c++ class

对于单个.cpp文件和.h文件 - 我们可以将实现从.cpp移动到.h文件,但我不能为我的情况做这个并且发生循环:

我的情况是这样的(包含保护被忽略):

// A.H

#include"stdio.h"
#include"b.h"

class A
{
public:
 void showfromA(const B& b);
 int index;
};

// a.cpp

#include"a.h"
void A::showfromA(const B& b)
{
printf("b.index=%i",b.index);
}

// b.h

 class B
{
public:
void showfromB();
int index;
};

// b.cpp

#include"a.h"
void B::showfromB()
{
A a;
a.index=1;
printf("a.index=%i",a.index);
}

// main.cpp中

#include"b.h"
main()
{
B b;
b.showfromB();
}
发生循环因为a.h包含b.h但b.cpp包含a.h. 当.h文件和.cpp文件分开,代码没问题时我们没有圆形但是当我们尝试合并.h文件和.cpp文件时,我们遇到了A类和B类之间的循环并编译错误。请注意,我想将.cpp文件中的方法植入移动到.h文件中的类定义*

4 个答案:

答案 0 :(得分:0)

如果您想将成员函数的定义移动到.h文件中,那么由于循环依赖性,它是不可能的。但是,您可以将定义移动到.h文件,但将它们保留在类定义之外。在后一种情况下,您必须使它们inline以避免链接器错误。

答案 1 :(得分:0)

通过在头文件中使用guard语句可以避免循环。

#ifndef _A_H
    #define _A_H
    //Code of A.h
#endif

同样的变化也可以在B.h中完成。

答案 2 :(得分:0)

这很尴尬,所以如果可以的话,我建议使用.cpp文件,但是如果你绝对需要在.h文件中内嵌所有内容,那么这样的话就可以了:< / p>

// main.cpp
#include "a.h"  // b.h will be included implicitly

int main(int, char**)
{
   A a;
   B b;
   a.showfromA(b);
   b.showfromB(a);
}

...

// a.h
#ifndef a_h
#define a_h

#include <stdio.h>
#include "b.h"

class B;

class A
{
public:
 void showfromA(const B & b) {printf("b's index is %i\n", b.index);}
 int index;
};

void B :: showfromB(const A & a) {printf("a's index is %i\n", a.index);}

#endif

...

// b.h -- don't #include this directly, include a.h instead
#ifndef b_h
#define b_h

#include <stdio.h>
#include "a.h"

class A;

class B
{
public:
 void showfromB(const A & a);    // implementation moved to a.h
 int index;
};

#endif

答案 3 :(得分:0)

您可以转发声明您的结构,以减少标头依赖性。

A.H

// we tell the compiler that B exists
struct B;

struct A {
    void showFromA(const B& b);
};

a.cpp

#include "a.h"
#include "b.h"

void A::showFromA(const B& b) {
    // B is complete here
}

b.h

// we tell the compiler that A exists
struct A;

struct B {
    void showFromB(const A& a);
};

b.cpp

#include "b.h"
#include "a.h"

void showFromB(const A& a) {
    // A is complete here
}

这种语法没问题,因为你接收引用作为参数。引用不需要完整,就像指针一样。但是,按值接收参数是行不通的,因为值语义要求类型完整。