CMake - 使用前向声明构建错误

时间:2017-12-08 03:30:35

标签: c++ cmake

我是C ++初学者,所以我正在为练习构建一个预算应用(创意,对吧?)。我正在使用CMake进行构建过程。我已经在另一个类中声明了一个类,我只有std::shared_ptr个不完整的类,但我仍然会遇到incomplete type个错误。这是CMake尝试在另一个类之前构建一个类的问题吗?如果是这种情况,有没有办法指定CMake Category之前需要构建Transaction?或者是否有关于前方声明的遗漏?

-- 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

Category.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);
    }
};

Transaction.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);
    }
};

Transaction.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;
}

1 个答案:

答案 0 :(得分:1)

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