【问题标题】:compiler cannot recognize my class in c++ - cyclic dependency编译器无法识别我在 C++ 中的类
【发布时间】:2022-01-09 16:57:44
【问题描述】:

拥有这个基类:

Core.hpp

#ifndef C3_CORE_HPP
#define C3_CORE_HPP

#include <c3/utils/Str.hpp>
#include <c3/utils/Vec.hpp>
#include <c3/school/Student.hpp>

class Core {
public:
    Core() = default;
    explicit Core(std::istream&in);
    virtual ~Core();

    virtual double grade() const;

    const Str &getName() const;
    double getMidterm() const;
    double getFinal() const;
    const Vec<double> &getHomeworks() const;

protected:
    Vec<double> homeworks;

    virtual std::istream &read(std::istream &in);
    virtual Core *clone() const;

    std::istream &read_common(std::istream &in);

private:
    Str name;
    double midterm{}, final{};

    friend class Student;
};

std::istream &read_hw(std::istream &in, Vec<double> &hws);

#endif //C3_CORE_HP

Grad.hpp

#ifndef C3_GRAD_HPP
#define C3_GRAD_HPP

#include <c3/school/Core.hpp>

class Grad: public Core {
public:
    Grad() = default;
    explicit Grad(std::istream &in);

    std::istream &read(std::istream &in) override;
    double grade() const override;

protected:
    Grad *clone() const override;

private:
    double thesis{};
};


#endif //C3_GRAD_HPP

(代码根据书accelerated C++ by Andrew Koenig创建)

现在这让我出错了:

In file included from /home/shepherd/Desktop/cpp/cpp0book/c3/./c3/school/Student.hpp:8,
                 from /home/shepherd/Desktop/cpp/cpp0book/c3/./c3/school/Core.hpp:10,
                 from /home/shepherd/Desktop/cpp/cpp0book/c3/c3/main.cpp:4:
/home/shepherd/Desktop/cpp/cpp0book/c3/./c3/school/Grad.hpp:10:25: error: expected class-name before ‘{’ token
   10 | class Grad: public Core {
      |                         ^
/home/shepherd/Desktop/cpp/cpp0book/c3/./c3/school/Grad.hpp:15:19: error: ‘std::istream& Grad::read(std::istream&)’ marked ‘override’, but does not override
   15 |     std::istream &read(std::istream &in) override;
      |                   ^~~~
/home/shepherd/Desktop/cpp/cpp0book/c3/./c3/school/Grad.hpp:16:12: error: ‘double Grad::grade() const’ marked ‘override’, but does not override
   16 |     double grade() const override;
      |            ^~~~~
/home/shepherd/Desktop/cpp/cpp0book/c3/./c3/school/Grad.hpp:19:11: error: ‘Grad* Grad::clone() const’ marked ‘override’, but does not override
   19 |     Grad *clone() const override;
      |           ^~~~~
In file included from /home/shepherd/Desktop/cpp/cpp0book/c3/./c3/school/Core.hpp:10,
                 from /home/shepherd/Desktop/cpp/cpp0book/c3/c3/main.cpp:4:
/home/shepherd/Desktop/cpp/cpp0book/c3/./c3/school/Student.hpp:26:5: error: ‘Core’ does not name a type
   26 |     Core *cp{};
      |     ^~~~
gmake[2]: *** [CMakeFiles/c3.dir/build.make:76: CMakeFiles/c3.dir/c3/main.cpp.o] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/c3.dir/all] Error 2
gmake: *** [Makefile:91: all] Error 2

第一个错误是

error: expected class-name before ‘{’ token
   10 | class Grad: public Core {

在我看来,即使包含 Core 类,编译器也无法识别。那么为什么编译器不能识别我的基类呢?

使用这个目录结构: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1204r0.html

github 仓库: https://github.com/Herdsmann/student_project.git

【问题讨论】:

  • 试试class Grad:之间的空格
  • @infinitezero 没有帮助
  • @milanHrabos 尝试将 all &lt;c3/school/Core.hpp&gt; 替换为 "c3/school/Core.hpp"。那是使用 &lt;&gt; 代替包含使用 "" 。对 每个 自定义包含的标题执行此操作。只需在所有自定义包含中将周围的&lt;&gt; 替换为""
  • @AnoopRana 我正在使用 open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1204r0.html ,这不鼓励使用 "" 包含
  • @milanHrabos 您可以尝试在 Grad.hpp 中将#include &lt;c3/school/Core.hpp&gt; 替换为#include "c3/school/Core.hpp",看看是否有效。这是包含文件时的常见问题,这就是我建议它的原因。样式指南就是:指南。您不一定非要遵循它们,尤其是当它们导致某种错误时。

标签: c++ inheritance g++ include


【解决方案1】:

正如我在评论中所说,问题是由于循环依赖。特别是,您的

Student.hpp 包括 --> Grad.hpp 又包括 --> Core.hpp 最后包括 --> Student.hpp

因此,正如您从上面看到的那样,您最终到达了起点,即 Student.cpp。这就是为什么它被称为循环依赖

解决,只需从 Core.hpp 中删除 #include &lt;c3/school/Student.hpp&gt;。这是因为对于朋友声明friend class Student,您不需要转发声明或包含Student 类。

所以修改/正确的 Core.hpp 文件如下所示:

#ifndef C3_CORE_HPP
#define C3_CORE_HPP

#include <c3/utils/Str.hpp>
#include <c3/utils/Vec.hpp>
//note i have removed the include header from here

class Core {
  //other members here as before

private:
    Str name;
    double midterm{}, final{};

    friend class Student;//THIS WORKS WITHOUT INCLUDING Student.hpp
};

std::istream &read_hw(std::istream &in, Vec<double> &hws);

#endif //C3_CORE_HPP

【讨论】:

    【解决方案2】:

    在 git 存储库中,文件 main.cpp 包含 Core.hpp,其中包含 Student.hpp 以获取朋友类 Student 的定义。在文件Student.hpp 中包含标题Grad.hpp,它本身包含Core.hpp。现在,由于Core.hpp 在包含Student.hpp 之前定义了包含保护C3_CORE_HPP,所以当Grad.hpp 包含Core.hpp 时,预处理器会跳过Core.hpp 的内容。这就是为什么在定义类 Grad 时,编译器不知道类 Core

    要解决此问题,您可以在 Core.hpp 中预定义类 Student 并省略包含:

    Core.hpp:

    #ifndef C3_CORE_HPP
    #define C3_CORE_HPP
    
    #include <c3/utils/Str.hpp>
    #include <c3/utils/Vec.hpp>
    
    class Student;
    
    class Core {
    
        // [...]
    
        friend class Student;
    };
    
    std::istream &read_hw(std::istream &in, Vec<double> &hws);
    
    #endif //C3_CORE_HP
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-12
      • 1970-01-01
      • 2020-11-13
      • 1970-01-01
      • 2020-12-14
      • 2014-08-17
      相关资源
      最近更新 更多