C ++ с использованием функций-членов с предварительным объявлением - PullRequest
0 голосов
/ 13 марта 2019

Я видел подобные вопросы, но не совсем как затруднительное положение, в котором я нахожусь. Я работаю с чужим кодом, и их структура такая:

//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, потому что затем я должен добавить его в зависимости dma_manager cmake, что означает, что я должен перечислить его в package.xml, и тогда он расстроится из-за циклической зависимости.Как я могу обойти это?Если бы я мог использовать члены error в db_manager, не делая ошибку зависимостью, я был бы хорош, я думаю, но я просто не могу понять, как это сделать.Я видел много других вопросов о предварительном объявлении, но для всех них заявленное использование классов не очень глубокое.Здесь я использую членов класса, а не просто объявляю указатель класса, как другие вопросы.

Я определенно мог бы использовать справку, я просто не вижу никакого логического способа сделать это без полного удаления пакета ошибок и записиновый.

Редактировать: также, я упростил это, но, возможно, я не должен был.error и db_manager находятся в двух отдельных пакетах.

1 Ответ

1 голос
/ 13 марта 2019

Первое: ваш пример очень плохой. Пожалуйста, предоставьте минимальный рабочий пример. Я понимаю, в чем ваша проблема (круговая зависимость), но ваш пример не показывает эту проблему. Это то, что вы должны решить на архитектурном уровне. Вы не можете решить это внутри CMake.

В зависимости от кода, который вы показали, вам не нужно включать db_manager.h в error.h, так как вы ничего не используете из db_manager во время объявления класса Error. Вам нужно только включить его в error.cpp, так как там вы используете один статический метод из db_manager. Таким образом, у вас нет круговой зависимости.

Ниже я добавил минимальный рабочий пример, который компилируется без ошибок.

error.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_ */

error.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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...