Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Wt::Dbo中的循环依赖_C++_Wt_Wt Dbo - Fatal编程技术网

C++ Wt::Dbo中的循环依赖

C++ Wt::Dbo中的循环依赖,c++,wt,wt-dbo,C++,Wt,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 persis

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);
  }
};
错误:C2079:“dummy”使用未定义的类“User”

可能的解决方案(我不喜欢)

  • 解决方案是在包含
    设置.h
    的每个cpp文件中包含
    User.h
    ,即:

    // test.cpp
    #include "User.h"
    #include "Settings.h"
    
    我不喜欢这个解决方案,因为每次我包括
    Settings.h
    时,我必须记住包括
    User.h

  • 另一种解决方案是使用非推荐的
    DBO_EXTERN_模板
    宏,即

    // Settings.h
    ...
    class Settings
    {
    public:
       ....
    };
    
    DBO_EXTERN_TEMPLATES(Settings)
    
    我不喜欢这个解决方案,因为这个宏不推荐,也没有文档记录<代码>DBO_外部模板不适用于所有编译器

  • 问题

    a。为了克服
    Wt::Dbo
    对象之间的循环依赖关系,避免所提到的
    未定义类
    错误,最好/首选的方法是什么

    b。为什么解决方案1。工作

    我创建了一个新的(一般-非
    Wt::Dbo
    specific)问题(带有MCVE),以澄清具体情况:

    参考资料

    • DBO_外部模板:
    • Wt::Dbo和循环相关性:
    • 给定的示例基于
      Wt::Dbo
      tutorial:,但我想将不同的类放入不同的头文件中

    我不熟悉
    Wt::Dbo
    ,但我不认为这个问题与它有关。它是一个更一般的C++类设计问题,需要你去处理它。它在C++项目中相当常见。 对于“最佳/首选方法”,这确实是一个意见问题。在您的情况下,如果仍然有转发声明,实际上可以同时使用
    User.h
    Settings.h
    来包含彼此

    例如,在
    设置.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
    。include基本上将内容复制到发生include的当前文件中。因此,实际上,您的
    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);
      }
    };
    
    //User.h
    #include//此处将包含此文档中的内容
    #include//此处将包含此文档中的内容
    //设置.h
    #include//由于之前的include和include保护,未包含内容
    #包括//同上
    类用户;//用户Wt::Dbo对象的前向声明
    班级设置
    {
    公众:
    Wt::Dbo::ptr用户;
    模板
    无效持续(行动与a)
    {
    Wt::Dbo::belongsTo(a,用户);
    }
    };
    类用户
    {
    公众:
    Wt::Dbo::弱ptr设置;
    模板
    无效持续(行动与a)
    {
    Wt::Dbo::hasOne(a,设置);
    }
    };
    
    您现在可以看到,当定义
    设置
    类时,
    用户
    已经被前向声明,并且可以由
    设置
    类使用。然后定义
    用户
    时,它具有要使用的
    设置
    的完整定义。现在,在
    test.cpp
    文件中,
    设置
    用户
    都已完全定义,因此可以使用


    我希望这会有所帮助:)

    根据ChrisMM的答案,另一个解决方案是在类的头文件顶部向前声明类:

    设置。h:

    // include guard
    class Settings;
    #include "User.h"
    
    class Settings { ... };
    
    用户.h:

    // include guard
    class User;
    #include "Settings.h"
    
    class User { ... };
    

    这种方法的优点是,您只需在自己的头文件中向前声明类,并且只允许将该文件包含在需要它的任何其他(头)文件中。

    用户是否依赖于
    设置
    ?@NathanOliver是的,它依赖于。我扩展了这个例子来阐明这一点。你可以让用户包含设置,反之亦然。只是不是两者都有。@ChrisMM,是的,我知道(并反映在我更新的问题中)。我想知道Wt::Dbo库希望它的用户如何处理这样的循环依赖关系。我也只是尝试在头文件中包含必要的文件,但由于每个包含
    设置.h
    的文件都必须包含
    user.h
    ,我不认为在
    设置.h
    中不包含
    user.h
    可以避免任何重新编译,是吗?我知道内容扩展到您所显示的内容,但我想知道何时使用
    用户
    类的定义(而不是转发声明),因为
    用户
    类仅在其定义之前使用?模板
    Wt::Dbo::ptr
    是否在文件末尾实例化?您的解决方案是否是一个格式错误的程序?在定义
    User
    类之前,实际上没有使用它;看起来就是这样
    Wt::Dbo::ptr
    大概是指针的包装器,指针不需要类的完整定义,直到它被实例化/使用。由于您没有实际实例化
    用户
    对象,也没有在
    设置
    类中调用其任何函数,因此它非常好,并且仍然是格式良好的。
    // include guard
    class Settings;
    #include "User.h"
    
    class Settings { ... };
    
    // include guard
    class User;
    #include "Settings.h"
    
    class User { ... };