【问题标题】:C++ using member functions with forward declarationC++ 使用带有前向声明的成员函数
【发布时间】:2019-08-04 02:42:07
【问题描述】:

我见过类似的问题,但与我发现自己所处的困境不太一样。我正在使用别人的代码,它们的结构是这样的。

//db_manager.h
class db_manager
{
  class error;
  bool logError(error::def_enum::Value v, string msg);

  bool read(int id);
}

//db_manager.cpp
#include db_manager.h
bool logError(error::def_enum::Value v, string msg)
{
    return error::logError(v, msg);
}

bool read(int id)
{
    //do db access stuff
    return true;
}

//error.h
#include db_manager
class error
{
  bool read(int id);
}

//error.cpp
#include error.h
bool read(int id)
{
    return db_manager::read(id);
}

bool logError(error::def_enum::Value v, string msg)
{
    //do error service stuff
}

这是一个非常明显的简化,但希望它能说明问题。

当我编译时,每当在 db_manager.cpp 中使用错误时,我都会收到很多不完整的类型错误,并且我无法将错误中的相关头文件包含到 db_manager.cpp 中,因为我必须将其添加到 db_managers cmake 依赖,这意味着我必须在 package.xml 中列出它,然后它会因循环依赖而变得不安。我怎样才能解决这个问题?如果我可以在 db_manager 中使用错误的成员而不使错误成为依赖项,我想我会很好,但我就是不知道该怎么做。我在这里看到了许多其他的前向声明问题,但对于所有这些问题,声明的类的使用都不是很深。这里我使用的是类成员,而不仅仅是像其他问题一样声明类指针。

我绝对可以使用帮助,我只是看不出有任何合乎逻辑的方法可以在不完全废弃错误包并编写新包的情况下执行此操作。

编辑:另外,我简化了这一点,但也许我不应该这样做。 error 和 db_manager 在两个单独的包中。

【问题讨论】:

  • 您对 CMake 和循环依赖的说法毫无意义。显然,您不能在 db_manager 标头中包含错误标头,但包含它 db_manager.cpp 应该非常好。
  • 循环头依赖只是头的问题。由于源文件通常不应该包含在内,它们不能成为循环依赖问题的一部分。尽管作为参考,here 是关于解决它们的问题。
  • db_manager 和错误在 2 个不同的包中。如果我尝试在 db_manager.cpp 中包含错误标头,编译器会说找不到它,这通常是因为 cmakelist 和/或 package.xml 没有包含错误作为依赖项的包.当然,如果我添加它,那么我们就有了循环依赖。

标签: c++ dependencies forward-declaration


【解决方案1】:

首先:您的示例非常糟糕。请提供一个最低限度的工作示例。我了解您的问题是什么(循环依赖),但您的示例未显示此问题。这是您必须在架构级别上解决的问题。你无法在 CMake 中解决这个问题。

根据您显示的代码,您不需要在 error.h 中包含 db_manager.h,因为在声明类 Error 期间您没有使用 db_manager 中的任何内容。您只需要将它包含在 error.cpp 中,因为您使用的是 db_manager 中的一种静态方法。这样你就没有任何循环依赖。

我在下面添加了一个最小工作示例,它编译时没有任何错误。

错误.h

#ifndef _ERROR_H_
#define _ERROR_H_

#include <string>

class Error
{
public:
  enum def_enum{ Val1, Val2};

  bool read(int id);
  static bool logError(def_enum v, std::string msg);
};

#endif /* _ERROR_H_ */

错误.cpp

#include "error.h"
#include "db_manager.h"

bool Error::read(int id)
{
    return db_manager::read(id);
}

bool Error::logError(Error::def_enum v, std::string msg)
{
    //do error service stuff
    return true;
}

db_manager.h

#ifndef _DB_MANAGER_H_
#define _DB_MANAGER_H_

#include <string>
#include "error.h"

class db_manager
{
public:
  static bool logError(Error::def_enum v, std::string msg);
  static bool read(int id);
};

#endif /* _DB_MANAGER_H_ */

db_manager.cpp

#include "db_manager.h"

bool db_manager::logError(Error::def_enum v, std::string msg)
{
    return Error::logError(v, msg);
}

bool db_manager::read(int id)
{
    //do db access stuff
    return true;
}

main.cpp

#include "db_manager.h"
#include "error.h"

int main(){


  db_manager::read(1);
  db_manager::logError(Error::Val1, "Test");

  Error e;
  e.read(2);

  return 0;
}

CMakeLists.txt

project(db_manager)

add_executable(executable main.cpp db_manager.cpp error.cpp)

【讨论】:

    猜你喜欢
    • 2012-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-13
    相关资源
    最近更新 更多