有人可以解释为什么我收到语法错误:在构建过程中在class Bar;
头文件中没有包含foo.hpp
的情况下,标识符'Bar'吗?
在构建之前,我没有在Visual Studio 2019中收到任何错误,并且构建顺序似乎依次为bar
,然后依次为foo
和main
,所以依次跟随{{1 }}语句,好像#include
头文件在构建期间首先包含在bar
头中。
我在下面包含了概述基本问题的代码。
foo
//Foo header file
#pragma once
#include "bar.hpp"
#include <iostream>
class Bar; //Commenting this line out results in no longer being able to build the project
class Foo {
public:
Foo();
void pickSomething(Bar& bar);
};
//Foo cpp file
#include "foo.hpp"
Foo::Foo() {
std::cout << "Made Foo" << std::endl;
}
void Foo::pickSomething(Bar& bar) {
bar.getSomething();
std::cout << "Picked something!" << std::endl;
}
//Bar header file
#pragma once
#include "foo.hpp"
#include <iostream>
class Foo;
class Bar {
public:
Bar(Foo& foo);
void getSomething();
};
//Bar cpp file
#include "bar.hpp"
Bar::Bar(Foo& foo) {
std::cout << "Made bar" << std::endl;
}
void Bar::getSomething() {
std::cout << "Gave something!" << std::endl;
}
答案 0 :(得分:1)
摘要:
foo.hpp
包括bar.hpp
,而bar.hpp
包括foo.hpp
。这是周期性的依赖关系。 #pragma once
确保不再加载相同的标头(如果已加载)。
仅bar.cpp
的编译失败(foo.cpp
和main.cpp
将被成功编译)
在编译bar.cpp
时,请遵循预处理程序。事情按以下顺序发生。
bar.cpp
包括bar.hpp
bar.hpp
包括foo.hpp
。 (注意以下两点)
bar.hpp
,并将避免在当前循环中再次输入它。Bar
(类Bar
的声明)仍未加载,因为之前已包含foo.hpp
foo.hpp
尝试包含bar.hpp
bar.hpp
,因此将其忽略!Foo
类声明使用称为Bar
的符号。但这没有在之前声明!未知符号Bar
可能表示很多东西(类,宏等)。因此,编译器(正确地)失败了,因为它不知道如何处理它。
解决方案是前向声明。在那里,您可以保证编译器Bar
代表一个类。只要您没有在编译器需要了解类布局的地方做任何事情(例如,定义类型为Bar
的成员函数,访问Bar
的成员函数等),编译就会成功。
答案 1 :(得分:0)
foo.hpp
和bar.hpp
彼此不依赖,因此前向声明是避免其头文件之间循环依赖的好方法。实际上,只有.cpp
个文件需要同时包含两个头文件。