CMake-具有正向声明的生成错误 我是C++初学者,所以我正在为实践构建一个预算应用程序(创意,对吗?)。我正在使用CMake进行构建过程。我已经在另一个类中向前声明了一个类,并且我只有std::shared_ptrs到不完整的类,但是我仍然得到complete type错误。这是CMake试图在一个类之前构建另一个类的问题吗?如果是这种情况,是否有办法指定在事务之前需要构建类别?或者我对远期申报有什么遗漏 -- 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 ——配置完成 --生成完成 --构建文件已写入:/hdd/lfs/projects/budget/Build make[1]:输入目录“/hdd/lfs/projects/budget/build” make[2]:输入目录“/hdd/lfs/projects/budget/build” make[3]:输入目录“/hdd/lfs/projects/budget/build” make[3]:离开目录“/hdd/lfs/projects/budget/build” make[3]:输入目录“/hdd/lfs/projects/budget/build” [16%]构建CXX对象cmakFiles/budget.dir/src/Transaction.cpp.o /hdd/lfs/projects/budget/src/Transaction.cpp:在构造函数“Transaction::Transaction(double,std::shared_ptr)”中: /hdd/lfs/projects/budget/src/Transaction.cpp:11:12:错误:无效使用不完整的类型“class Category” _类别->添加事务(*此); ^ 在/hdd/lfs/projects/budget/src/Transaction.cpp:3:0中包含的文件中: /hdd/lfs/projects/budget/include/Transaction.h:10:7:注:转发“类别”声明 类别; ^ /hdd/lfs/projects/budget/src/Transaction.cpp:在构造函数“Transaction::Transaction(double,std::_ucxx11::string,std::shared_ptr)”中: /hdd/lfs/projects/budget/src/Transaction.cpp:21:12:错误:无效使用不完整的类型“class Category” _类别->添加事务(*此); ^ 在/hdd/lfs/projects/budget/src/Transaction.cpp:3:0中包含的文件中: /hdd/lfs/projects/budget/include/Transaction.h:10:7:注:转发“类别”声明 类别; ^ /hdd/lfs/projects/budget/src/Transaction.cpp:在析构函数“Transaction::~Transaction()”中: /hdd/lfs/projects/budget/src/Transaction.cpp:26:12:错误:无效使用不完整的类型“class Category” _类别->删除交易(*此); ^ 在/hdd/lfs/projects/budget/src/Transaction.cpp:3:0中包含的文件中: /hdd/lfs/projects/budget/include/Transaction.h:10:7:注:转发“类别”声明 类别; ^ CMakeFiles/budget.dir/build.make:158:目标“CMakeFiles/budget.dir/src/Transaction.cpp.o”的配方失败 make[3]:***[CMakeFiles/budget.dir/src/Transaction.cpp.o]错误1 make[3]:离开目录“/hdd/lfs/projects/budget/build” CMakeFiles/Makefile2:67:目标“CMakeFiles/budget.dir/all”的配方失败 生成[2]:***[CMakeFiles/budget.dir/all]错误2 make[2]:离开目录“/hdd/lfs/projects/budget/build” Makefile:83:目标“全部”的配方失败 生成[1]:***[all]错误2 make[1]:离开目录“/hdd/lfs/projects/budget/build” makefile:2:目标“全部”的配方失败 make:**[全部]错误2 h类 #pragma一次 #包括 #包括 #包括“Transaction.h” 类别 { 私人: std::string _name; 双倍预算; 双平衡; std::列表_事务; void calculateBalance(); 公众: 类别()=删除; 类别(标准::字符串名称) :\单位名称(名称),\单位预算(0),\单位余额(0) {} std::string name()常量; void setName(std::string name); 双预算()常数; 作废预算(双倍预算); 双平衡常数; 作废交易(交易&交易); 作废交易(交易&交易); std::ostream&display(std::ostream&out)const; 布尔运算符==(常量类别&右侧)常量; 布尔运算符!=(常量类别和右侧)常量; friend std::ostream&operator

CMake-具有正向声明的生成错误 我是C++初学者,所以我正在为实践构建一个预算应用程序(创意,对吗?)。我正在使用CMake进行构建过程。我已经在另一个类中向前声明了一个类,并且我只有std::shared_ptrs到不完整的类,但是我仍然得到complete type错误。这是CMake试图在一个类之前构建另一个类的问题吗?如果是这种情况,是否有办法指定在事务之前需要构建类别?或者我对远期申报有什么遗漏 -- 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 ——配置完成 --生成完成 --构建文件已写入:/hdd/lfs/projects/budget/Build make[1]:输入目录“/hdd/lfs/projects/budget/build” make[2]:输入目录“/hdd/lfs/projects/budget/build” make[3]:输入目录“/hdd/lfs/projects/budget/build” make[3]:离开目录“/hdd/lfs/projects/budget/build” make[3]:输入目录“/hdd/lfs/projects/budget/build” [16%]构建CXX对象cmakFiles/budget.dir/src/Transaction.cpp.o /hdd/lfs/projects/budget/src/Transaction.cpp:在构造函数“Transaction::Transaction(double,std::shared_ptr)”中: /hdd/lfs/projects/budget/src/Transaction.cpp:11:12:错误:无效使用不完整的类型“class Category” _类别->添加事务(*此); ^ 在/hdd/lfs/projects/budget/src/Transaction.cpp:3:0中包含的文件中: /hdd/lfs/projects/budget/include/Transaction.h:10:7:注:转发“类别”声明 类别; ^ /hdd/lfs/projects/budget/src/Transaction.cpp:在构造函数“Transaction::Transaction(double,std::_ucxx11::string,std::shared_ptr)”中: /hdd/lfs/projects/budget/src/Transaction.cpp:21:12:错误:无效使用不完整的类型“class Category” _类别->添加事务(*此); ^ 在/hdd/lfs/projects/budget/src/Transaction.cpp:3:0中包含的文件中: /hdd/lfs/projects/budget/include/Transaction.h:10:7:注:转发“类别”声明 类别; ^ /hdd/lfs/projects/budget/src/Transaction.cpp:在析构函数“Transaction::~Transaction()”中: /hdd/lfs/projects/budget/src/Transaction.cpp:26:12:错误:无效使用不完整的类型“class Category” _类别->删除交易(*此); ^ 在/hdd/lfs/projects/budget/src/Transaction.cpp:3:0中包含的文件中: /hdd/lfs/projects/budget/include/Transaction.h:10:7:注:转发“类别”声明 类别; ^ CMakeFiles/budget.dir/build.make:158:目标“CMakeFiles/budget.dir/src/Transaction.cpp.o”的配方失败 make[3]:***[CMakeFiles/budget.dir/src/Transaction.cpp.o]错误1 make[3]:离开目录“/hdd/lfs/projects/budget/build” CMakeFiles/Makefile2:67:目标“CMakeFiles/budget.dir/all”的配方失败 生成[2]:***[CMakeFiles/budget.dir/all]错误2 make[2]:离开目录“/hdd/lfs/projects/budget/build” Makefile:83:目标“全部”的配方失败 生成[1]:***[all]错误2 make[1]:离开目录“/hdd/lfs/projects/budget/build” makefile:2:目标“全部”的配方失败 make:**[全部]错误2 h类 #pragma一次 #包括 #包括 #包括“Transaction.h” 类别 { 私人: std::string _name; 双倍预算; 双平衡; std::列表_事务; void calculateBalance(); 公众: 类别()=删除; 类别(标准::字符串名称) :\单位名称(名称),\单位预算(0),\单位余额(0) {} std::string name()常量; void setName(std::string name); 双预算()常数; 作废预算(双倍预算); 双平衡常数; 作废交易(交易&交易); 作废交易(交易&交易); std::ostream&display(std::ostream&out)const; 布尔运算符==(常量类别&右侧)常量; 布尔运算符!=(常量类别和右侧)常量; friend std::ostream&operator,c++,cmake,C++,Cmake,您的Transaction.cpp文件只包含Transaction.h,它不包含Category的定义。因此,在Transaction.cpp的上下文中,编译器不允许您访问Category类型的任何对象的成员ory.h在Transaction.cpp中来解决您的问题。您需要#包括“Category.h”在Transaction.cpp中@songyuanyao谢谢!这是切题相关的,但我的印象是,我通常不应该在.cpp文件中包含头文件,除非它包含.cpp文件实现的原型。我完全错了吗?类别需要在中完

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

您需要
#包括“Category.h”
Transaction.cpp
中@songyuanyao谢谢!这是切题相关的,但我的印象是,我通常不应该在.cpp文件中包含头文件,除非它包含.cpp文件实现的原型。我完全错了吗?
类别
需要在
中完整键入action.cpp
,因为您正在调用其成员函数。然后您必须包含其头文件。是的,不包含不必要的头文件是正确的。可能重复
#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);
    }
};
#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);
    }
};
#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;
}