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

How can we move implementation to multiple header file without circularity?

本文关键字:移动 实现 文件 情况下 循环 我们      更新时间:2023-10-16

对于单个.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);
}

主.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 文件中的 * 类定义*

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

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

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

类似的更改也可以在 B.h 中进行。

这很尴尬,所以我建议如果可以的话使用 .cpp 文件,但如果你绝对需要所有内容都内联在 .h 文件中,这样的事情就可以了:

// 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 %in", b.index);}
 int index;
};
void B :: showfromB(const A & a) {printf("a's index is %in", 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

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

A.H

// we tell the compiler that B exists
struct B;
struct A {
    void showFromA(const B& b);
};

答.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);
};

乙.cpp

#include "b.h"
#include "a.h"
void showFromB(const A& a) {
    // A is complete here
}

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