编译器无法识别循环依赖关系中的类



具有以下基类:

核心.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

(代码是根据Andrew Koenig的加速C++一书创建的)

现在这让我出错:

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

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

Student.hpp 包括 --> Grad.hpp 而 Grad.hpp 又包括 --> Core.hpp,最终包括 -->Student.hpp

所以从上面可以看到,你最终到达了你开始的地方,即在Student.hpp。这就是为什么它被称为循环依赖

解决此问题,只需从Core.hpp中删除#include <c3/school/Student.hpp>即可。这是因为对于 friend 声明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 

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

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

核心.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

相关内容

  • 没有找到相关文章

最新更新