我不确定我是否问过最明确的问题,因此请原谅我是否出于观点。
在编程中,我通常遵循这样的哲学:如果一个库属于.cpp
文件,那么它应该属于.hpp
文件。但是,对于OOP,这不一定适用。我想出了一个非常小的例子:
Class1来源:
#include "class1.hpp"
int Class1::getOther(Class2 *obj)
{
return obj->get();
}
void Class1::setOther(Class2 *obj, int val)
{
obj->set(val);
}
Class1标头:
#ifndef CLASS_1_HPP
#define CLASS_1_HPP
#include "class2.hpp"
class Class1
{
public:
int getOther(Class2 *obj);
void setOther(Class2 *obj, int val);
int get() const { return value; }
void set(int val) { value = val; }
private:
int value;
};
#endif
Class2来源:
#include "class1.hpp" // Placed here instead of class2.hpp
#include "class2.hpp"
int Class2::getOther(Class1 *obj)
{
return obj->get();
}
void Class2::setOther(Class1 *obj, int val)
{
obj->set(val);
}
Class2标头:
#ifndef CLASS_2_HPP
#define CLASS_2_HPP
class Class1; // Forward Declaration
class Class2
{
public:
int getOther(Class1 *obj);
void setOther(Class1 *obj, int val);
int get() const { return value; }
void set(int val) { value = val; }
private:
int value;
};
#endif
主要:
#include <iostream>
#include "class1.hpp"
int main()
{
Class1 *A = new Class1;
Class2 *B = new Class2;
A->setOther(B,15);
A->set(A->getOther(B));
std::cout << "A: " << B->getOther(A) << " B: " << A->getOther(B) << std::endl;
delete A;
delete B;
}
这是一个简单的示例,不一定要相互依赖。但是,为了编译该代码,我们必须将class1.hpp
从class2.hpp
移到class2.cpp
。然后要解决此问题,我们在Class1
中创建Class2
的前向声明。由于两个标头不会冲突,因此摆脱了循环依赖关系,Class1
和Class2
现在将可以安全地相互了解。
编程时,我将头文件和源文件都视为一个完整的对象。或者,该源文件只是头文件的扩展,并且扩展了头文件的所有定义。在这种情况下,我要做的是创建一个知道Class1
和Class2
的驱动程序类,并控制它们。
此实现如何避免循环依赖?编译器如何编译它而不捕获任何可能的循环依赖关系?最后,什么时候需要以这种方式使用前向声明?