Wt::D bo 中的循环依赖关系
Circular dependency in Wt::Dbo
Wt 建议使用前向声明以避免循环依赖。
// Settings.h
#include <Wt/Dbo/Dbo.h>
#include <string>
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);
}
};
// User.h
#include <Wt/Dbo/Dbo.h>
#include <string>
#include "Settings.h"
class User
{
public:
Wt::Dbo::weak_ptr<Settings> settings;
template<class Action>
void persist(Action& a)
{
Wt::Dbo::hasOne(a, settings);
}
};
但是,当我在另一个 cpp 文件中使用此Settings
类时,程序无法编译:
// test.cpp
#include "Settings.h"
错误: C2079:"虚拟"使用未定义的类"用户">
可能的解决方案(我不喜欢(
一种解决方案是包含在包含
Settings.h
的每个 cpp 文件中的User.h
中,即:// test.cpp #include "User.h" #include "Settings.h"
我不喜欢这个解决方案,因为我必须记住每次包含
User.h
时都包含Settings.h
.另一种解决方案是使用不推荐的
DBO_EXTERN_TEMPLATES
宏,即// Settings.h ... class Settings { public: .... }; DBO_EXTERN_TEMPLATES(Settings)
我不喜欢这个解决方案,因为不推荐这个宏,也不记录。
DBO_EXTERN_TEMPLATES
不适用于所有编译器。
问题
一个。克服Wt::Dbo
对象之间的循环依赖关系的最佳/首选方法是什么,避免上述undefined class
错误?
b.为什么解决方案 1. 有效?
我创建了一个新的(一般 - 不是Wt::Dbo
特定(问题(使用 MCVE(,以澄清具体情况:模板化类的成员函数何时实例化?
引用
- DBO_EXTERN_TEMPLATES:https://www.mail-archive.com/witty-interest@lists.sourceforge.net/msg06963.html
- Wt::D bo和循环:https://redmine.webtoolkit.eu/boards/2/topics/290?r=292
- 给定的示例基于
Wt::Dbo
教程:https://www.webtoolkit.eu/wt/doc/tutorial/dbo.html#_em_one_to_one_em_relations,但我想将不同的类放入不同的头文件中。
我不熟悉Wt::Dbo
,但我认为这个问题并不具体。这更像是一个一般的C++类设计问题,您需要解决/处理;这实际上在C++项目中相当常见。
对于"最佳/首选方法",这确实是一个意见问题。在您的情况下,如果您仍然具有前向声明,您实际上可以同时包含User.h
和Settings.h
。
例如,在Settings.h
:
// include guard
class User;
#include "User.h"
class Settings { ... };
那么在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
和User
都是完全定义的,因此可以使用。
我希望这对:)有所帮助
根据 ChrisMM 的回答,另一种解决方案是在其头文件的顶部转发声明您的类:
设置.h:
// include guard
class Settings;
#include "User.h"
class Settings { ... };
用户.h:
// include guard
class User;
#include "Settings.h"
class User { ... };
此方法的优点是,您只需在其自己的头文件中转发声明类,并且只允许将该文件包含在需要它的任何其他(头(文件中。
- C++GTKMM gui循环依赖关系
- 如何在头文件中声明类模板(由于循环依赖关系)
- 如何在具有循环依赖的类中dynamic_cast?
- C++模板方法中的循环依赖关系
- 修复循环依赖项 c++17 标头
- 涉及全局对象的循环依赖C++
- 循环依赖,在继承类的情况下使用覆盖方法
- Wt::D bo 中的循环依赖关系
- 在包含窗口标头时难以解决循环依赖关系问题
- 解决循环依赖关系 c++ 的想法
- C++循环依赖关系,未声明的标识符
- C++ 中的循环依赖关系问题
- 错误 C2512 视觉C++(并且不是循环依赖项)
- CMake 外部和内部静态库的循环依赖关系
- 正在从继承中解析循环依赖项
- "std::shared_ptr"循环依赖关系是如何导致问题的
- 纯引用而不是weak_ptr来打破循环依赖关系
- "invalid use of incomplete type" .解决循环依赖关系
- 如何避免模板方法的循环依赖
- 循环依赖结构,使用前向声明时结构的错误重定义