c++ - CMake - 前向声明构建错误

标签 c++ cmake

我是 C++ 初学者,所以我正在构建一个预算应用程序(创意,对吧?)以供练习。我在构建过程中使用 CMake。我已经在另一个类中转发声明了一个类,并且我只有 std::shared_ptr 到不完整的类,但我仍然遇到 incomplete type 错误。这是 CMake 尝试先构建一个类的问题吗?如果是这样的话,有没有办法向 CMake 指定 Category 需要在 Transaction 之前构建?或者我在前向声明(forward declaration)中遗漏了什么?

-- Configuring done
-- Generating done
-- Build files have been written to: /hdd/lfs/projects/budget/build
make[1]: Entering directory '/hdd/lfs/projects/budget/build'
make[2]: Entering directory '/hdd/lfs/projects/budget/build'
make[3]: Entering directory '/hdd/lfs/projects/budget/build'
make[3]: Leaving directory '/hdd/lfs/projects/budget/build'
make[3]: Entering directory '/hdd/lfs/projects/budget/build'
[ 16%] Building CXX object CMakeFiles/budget.dir/src/Transaction.cpp.o
/hdd/lfs/projects/budget/src/Transaction.cpp: In constructor ‘Transaction::Transaction(double, std::shared_ptr<Category>)’:
/hdd/lfs/projects/budget/src/Transaction.cpp:11:12: error: invalid use of incomplete type ‘class Category’
   _category->addTransaction(*this);
            ^
In file included from /hdd/lfs/projects/budget/src/Transaction.cpp:3:0:
/hdd/lfs/projects/budget/include/Transaction.h:10:7: note: forward declaration of ‘class Category’
 class Category;
       ^
/hdd/lfs/projects/budget/src/Transaction.cpp: In constructor ‘Transaction::Transaction(double, std::__cxx11::string, std::shared_ptr<Category>)’:
/hdd/lfs/projects/budget/src/Transaction.cpp:21:12: error: invalid use of incomplete type ‘class Category’
   _category->addTransaction(*this);
            ^
In file included from /hdd/lfs/projects/budget/src/Transaction.cpp:3:0:
/hdd/lfs/projects/budget/include/Transaction.h:10:7: note: forward declaration of ‘class Category’
 class Category;
       ^
/hdd/lfs/projects/budget/src/Transaction.cpp: In destructor ‘Transaction::~Transaction()’:
/hdd/lfs/projects/budget/src/Transaction.cpp:26:12: error: invalid use of incomplete type ‘class Category’
   _category->deleteTransaction(*this);
            ^
In file included from /hdd/lfs/projects/budget/src/Transaction.cpp:3:0:
/hdd/lfs/projects/budget/include/Transaction.h:10:7: note: forward declaration of ‘class Category’
 class Category;
       ^
CMakeFiles/budget.dir/build.make:158: recipe for target 'CMakeFiles/budget.dir/src/Transaction.cpp.o' failed
make[3]: *** [CMakeFiles/budget.dir/src/Transaction.cpp.o] Error 1
make[3]: Leaving directory '/hdd/lfs/projects/budget/build'
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/budget.dir/all' failed
make[2]: *** [CMakeFiles/budget.dir/all] Error 2
make[2]: Leaving directory '/hdd/lfs/projects/budget/build'
Makefile:83: recipe for target 'all' failed
make[1]: *** [all] Error 2
make[1]: Leaving directory '/hdd/lfs/projects/budget/build'
makefile:2: recipe for target 'all' failed
make: *** [all] Error 2

类别.h

#pragma once

#include <string>
#include <list>

#include "Transaction.h"

class Category
{
  private:
    std::string _name;
    double _budget;
    double _balance;
    std::list<Transaction> _transactions;

    void calculateBalance();


  public:
    Category() =delete;

    Category(std::string name)
      : _name(name), _budget(0), _balance(0)
    {}

    std::string name() const;
    void setName(std::string name);

    double budget() const;
    void setBudget(double budget);

    double balance() const;

    void addTransaction(Transaction& transaction);

    void deleteTransaction(Transaction& transaction);

    std::ostream& display(std::ostream& out) const;

    bool operator==(const Category& right) const;

    bool operator!=(const Category& right) const;

    friend std::ostream& operator<<(std::ostream& out, const Category& c)
    {
      return c.display(out);
    }
};

事务.h

#pragma once

#include <iostream>
#include <memory>

#include "boost/date_time/gregorian/gregorian.hpp"

#include "DisplayHelpers.h"

class Category;

class Transaction
{
  private:
    std::string _description;
    double _amount;
    boost::gregorian::date _date;
    std::shared_ptr<Category> _category;

  public:
    Transaction() = delete;

    Transaction(double amount, std::shared_ptr<Category> category);

    Transaction(double amount, std::string description, 
                std::shared_ptr<Category> category);

    ~Transaction();

    void setDescription(std::string description);
    std::string getDescription() const;

    void setAmount(double amount);
    double getAmount() const;

    boost::gregorian::date getDate() const;

    void setCategory(std::shared_ptr<Category> c);
    std::shared_ptr<Category> getCategory() const;


    bool operator==(const Transaction& other) const;
    bool operator<(const Transaction& other) const;

    std::ostream&  display(std::ostream& out) const;

    friend std::ostream& operator<<(std::ostream& out, const Transaction& t)
    {
      return t.display(out);
    }
};

交易.cpp

#include "Transaction.h"

Transaction::Transaction(double amount, std::shared_ptr<Category> category)
  : _amount(amount), 
    _date(boost::gregorian::day_clock::local_day()),
    _description("Transaction"), 
    _category(category)
{
  _category->addTransaction(*this);
}

Transaction::Transaction(double amount, std::string description, 
            std::shared_ptr<Category> category)
  : _amount(amount), 
    _date(boost::gregorian::day_clock::local_day()),
    _description(description),
    _category(category)
{
  _category->addTransaction(*this);
}

Transaction::~Transaction()
{
  _category->deleteTransaction(*this);
}

void Transaction::setDescription(std::string description) 
{
  _description = description;
}

std::string Transaction::getDescription() const
{
  return _description;
}

void Transaction::setAmount(double amount) {_amount = amount;}
double Transaction::getAmount() const {return _amount;}

void Transaction::setCategory(std::shared_ptr<Category> category)
{
  _category = category;
}
std::shared_ptr<Category> Transaction::getCategory() const
{
  return _category;
}

std::ostream&  Transaction::display(std::ostream& out=std::cout) const 
{
  std::string amountString = DisplayHelpers::monify(_amount);

  out << std::setw(14) << std::left << "Description: " << _description << "\n";
  out << std::setw(13) << std::left << "Amount: " << amountString << "\n";
  out << std::setw(14) << std::left << "Date: " << _date << "\n";

  return out;
}

bool Transaction::operator==(const Transaction& other) const
{
  return (_description == other._description &&
          _amount == other._amount && 
          _date == other._date && 
          _category == other._category);
}

bool Transaction::operator<(const Transaction& other) const
{
    bool returnStatus = false;
    if (_date > other._date)
    {
        returnStatus = false;
    }
    else 
        {
          if (_amount < other._amount)
          {
            returnStatus = true;
          }
    }
    return returnStatus;
}

最佳答案

您的 Transaction.cpp 文件仅包含 Transaction.h,其中不包含 Category 的定义。因此,在 Transaction.cpp 的上下文中,编译器不允许您访问类型为 Category 的任何对象的成员。在 Transaction.cpp 中包含 Category.h 以解决您的问题。

关于c++ - CMake - 前向声明构建错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47707284/

相关文章:

c++ - 如何删除指向指针的指针?

c++ - 安全回调设计

c++ - 如何使用 CMake 查找使用 VS 2017 编译的 Boost 文件系统库?

cmake - 如何在 CMake 中使用 find_package? (例如 : GMP library)

CMake与STREQUAL的空字符串比较失败

c++ - 使用带有 boost 绑定(bind)的 boost 函数与 map

c# - 从 C# 迁移到 C++(加上在同一解决方案中使用两者)

c++ - 找到二叉树中最低的叶子

C++ cmake & boost & arm 交叉编译

c++ - CMake目录层次结构,独立构建子目录