我不熟悉Wt::Dbo
,但我不认为这个问题是特定的。这更像是一个一般的 C++ 类设计问题,您需要解决/处理它;它实际上在 C++ 项目中相当常见。
对于“最佳/首选方法”,这确实是一个见仁见智的问题。就你而言,你实际上可以两者兼得User.h
and Settings.h
如果您还有前向声明,请相互包括在内。
例如,在Settings.h
:
// include guard
class User;
#include "User.h"
class Settings { ... };
Then in User.h
, 你可以做:
// include guard
class Settings;
#include "Settings.h"
class User { ... };
我知道这看起来很奇怪,但这是一种确保您不必始终包含两个标头的方法。或者,您只需在一个标头中执行此操作,并确保您始终包含该标头。
一般来说,我首选的方法是,在头文件中,仅包含头文件中绝对需要的内容,并向前声明其余部分。然后,我在源文件中包含实际需要的标头。这样做的原因是,如果我需要更改一个头文件,我不必重新编译包含该头文件的所有源文件;它提高了编译过程的性能。
至于您关于为什么解决方案 1 有效的问题,这是因为您包含文件的方式。在该特定示例中,您甚至不需要包括Settings.h
在源文件中,因为User.h
已经这样做了。但让我们看看预处理器处理完后它会是什么样子。
当你包括User.h
,它首先包括Settings.h
。包含基本上将内容复制到发生包含的当前文件中。所以,有效地,你的User.h
看起来像这样:
// User.h
#include <Wt/Dbo/Dbo.h> // contents from this would be here
#include <string> // contents from this would be here
// Settings.h
#include <Wt/Dbo/Dbo.h> // contents NOT included, due to previous include and include guards
#include <string> // same as above
class User; // Forward declaration of User Wt::Dbo object
class Settings
{
public:
Wt::Dbo::ptr<User> user;
template<class Action>
void persist(Action& a)
{
Wt::Dbo::belongsTo(a, user);
}
};
class User
{
public:
Wt::Dbo::weak_ptr<Settings> settings;
template<class Action>
void persist(Action& a)
{
Wt::Dbo::hasOne(a, settings);
}
};
你现在看到的是,当Settings
正在定义类,User
已经向前声明并且可以被使用Settings
班级。什么时候User
然后定义,它有完整的定义Settings
跟...共事。在你的test.cpp
现在归档,两者Settings
and User
已完全定义,因此可以使用。
我希望这有帮助 :)