在处理循环引用时,在适当的情况下使用前向声明而不是#include 语句。
另外,头文件本身应该有保护,以避免在#include'd 多次声明其内容时多次声明其内容。守卫本身可以使用#ifndef/#define 对或#pragma once,具体取决于您的编译器。
啊.h
#ifndef A_H
#define A_H
struct B;
struct A
{
virtual B* f() = 0;
};
#endif
或者:
#pragma once
struct B;
struct A
{
virtual B* f() = 0;
};
A1.h:
#ifndef A1_H
#define A1_H
#include "A.h"
struct B1;
struct A1 : public A
{
B1* f() override;
};
#endif
或者:
#pragma once
#include "A.h"
struct B1;
struct A1 : public A
{
B1* f() override;
};
A2.h
#ifndef A2_H
#define A2_H
#include "A.h"
struct B2;
struct A2 : public A
{
B2* f() override;
};
#endif
或者:
#pragma once
#include "A.h"
struct B2;
struct A2 : public A
{
B2* f() override;
};
B.h
#ifndef B_H
#define B_H
struct A;
struct B
{
virtual A* g() = 0;
};
#endif
或者:
#pragma once
struct A;
struct B
{
virtual A* g() = 0;
};
B1.h
#ifndef B1_H
#define B1_H
#include "B.h"
struct A1;
struct B1 : public B
{
A1* g() override;
};
#endif
或者:
#pragma once
#include "B.h"
struct A1;
struct B1 : public B
{
A1* g() override;
};
B2.h
#ifndef B2_H
#define B2_H
#include "B.h"
struct A2;
struct B2
{
A2* g() override;
};
#endif
或者
#pragma once
#include "B.h"
struct A2;
struct B2
{
A2* g() override;
};
满足前向声明类的#include语句应该在方法实现源文件中使用,而不是在它们的声明头文件中:
A1.cpp:
#include "A1.h"
#include "B1.h" // <--
B1* A1::f()
{
return new B1; // or wherever the B1 object comes from...
}
A2.h
#include "A2.h"
#include "B2.h" // <--
B2* A2::f()
{
return new B2; // or wherever the B2 object comes from...
}
B1.cpp
#include "B1.h"
#include "A1.h" // <--
A1* B1::g()
{
return new A1; // or wherever the A1 object comes from...
}
B2.cpp
#include "B2.h"
#include "A2.h" // <--
A2* B2::g()
{
return new A2; // or wherever the A2 object comes from...
}
话虽如此,向前声明结构是处理循环引用的唯一方法。但是由于您无法转发声明层次结构,因此我认为如果不重新考虑您的设计就无法解决您的问题。如果这不是一个选项,您将不得不远离使用协变返回值。
啊.h
#pragma once
struct B;
struct A
{
virtual B* f() = 0;
};
A1.h:
#pragma once
#include "A.h"
struct A1 : public A
{
B* f() override;
};
A2.h
#pragma once
#include "A.h"
struct A2 : public A
{
B* f() override;
};
B.h
#pragma once
struct A;
struct B
{
virtual A* g() = 0;
};
B1.h
#pragma once
#include "B.h"
struct B1 : public B
{
A* g() override;
};
B2.h
#pragma once
#include "B.h"
struct B2
{
A* g() override;
};
A1.cpp:
#include "A1.h"
#include "B1.h" // <--
B* A1::f()
{
return new B1; // or wherever the B1 object comes from...
}
A2.h
#include "A2.h"
#include "B2.h" // <--
B* A2::f()
{
return new B2; // or wherever the B2 object comes from...
}
B1.cpp
#include "B1.h"
#include "A1.h" // <--
A* B1::g()
{
return new A1; // or wherever the A1 object comes from...
}
B2.cpp
#include "B2.h"
#include "A2.h" // <--
A* B2::g()
{
return new A2; // or wherever the A2 object comes from...
}
这只是意味着在调用 f() 和 g() 时,无论您在哪里依赖协方差,都必须使用类型转换。