C:\码块\库尔\ praks2 \ SRC .. \包括\ circle2.h | 8 |错误: 'Line2'没有命名类型| C:\代码块\库尔\ praks2的\ src .. \包括\ circle2.h | 17 |错误: 'Line2'尚未声明| || === 构建完成:2个错误,0个警告 === |
circle2.h:
#ifndef CIRCLE2_H
#define CIRCLE2_H
#include "geometry.h"
class Circle2 {
public:
Vector2 p1;
float r;
Circle2();
Circle2(Vector2 np1, float nr);
float circumference();
float area();
bool contains(Vector2 v);
bool contains(Line2 l); // error is here.
void scale(float factor);
friend ostream& operator <<(ostream& out, const Circle2& cir);
};
#endif // CIRCLE2_H
circle.cpp:
bool Circle2::contains(Line2 l) {
return 0;
}
geometry.h:
#ifndef GEOMETRY_H
#define GEOMETRY_H
// These are needed to use the functions in our library
#include <iostream>
using namespace std;
// Include own headers
// NB! Add your own headers here!
#include "vector2.h"
#include "line2.h"
#include "circle2.h"
#endif // GEOMETRY_H
这是circle2.cpp:
#include "../include/circle2.h"
#include <math.h>
Circle2::Circle2() {
p1 = Vector2();
r = 0;
}
Circle2::Circle2(Vector2 np1, float nr) {
p1 = np1;
r = nr;
}
float Circle2::circumference() {
return 2 * r * M_PI;
}
float Circle2::area() {
return pow(r, 2) * M_PI;
}
bool Circle2::contains(Vector2 v) {
if(p1.distanceFrom(v) <= r) return 1;
return 0;
}
bool Circle2::contains(Line2 l) {
return 0;
}
void Circle2::scale(float factor) {
r *= factor;
}
ostream& operator<<(ostream& out, const Circle2& cir) {
out << "(" << cir.p1 << ", " << cir.r << ")";
return out;
}
line2.cpp:
#include "../include/line2.h"
#include <math.h>
Line2::Line2() {
p1 = Vector2();
p2 = Vector2();
}
Line2::Line2(Vector2 np1, Vector2 np2) {
p1 = np1;
p2 = np2;
}
float Line2::length() {
return p1.distanceFrom(p2);
}
ostream& operator<<(ostream& out, const Line2& line) {
out << "(" << line.p1 << " - " << line.p2 << ")";
return out;
}
line2.h:
#ifndef LINE2_H
#define LINE2_H
#include "geometry.h"
class Line2 {
public:
Vector2 p1;
Vector2 p2;
Line2();
Line2(Vector2 np1, Vector2 np2);
float length();
friend ostream& operator <<(ostream& out, const Line2& line);
};
#endif // LINE2_H
答案 0 :(得分:2)
你现在已经尝试了其他所有内容。这会让你陷入麻烦。
看起来Line2需要了解Vector2;和Circle2需要知道Line2和Vector2。 Vector2是独立的,还是尝试使用Line2或Circle2?
如果它独立,那么你只需要让Line2包含Vector2,而Circle2包含Line2和Vector2。然后删除在圆圈中运行的其他包含语句(例如,Circle2包含包含Circle2的几何图形......)。
如果Vector2尝试使用Line2或Circle2,则您将具有循环依赖关系。以下是解决这个问题的方法:
#include
语句(只是几何/ Circle2 /等)Line2
,取const Line2&
)#include
您需要的形状的头文件。这种方式的工作方式是头文件不再依赖于其他形状,因此它打破了循环包含循环。 Circle2.cpp
包括Line2.h
,但Line2.h
不包含Circle2.h
,因此周期结束。
前向声明该类告诉编译器“有一个名为Line2
的类,但您还不需要知道它的任何细节”。更改方法以使用引用(或指针)允许编译器在处理标头时不需要任何类详细信息。
当编译器处理源代码(您实际上在其他类中执行某些操作)时,它现在需要知道另一个类的详细信息。这就是您需要在源文件中包含完整的类定义的原因。
编辑:关于包含警卫和循环包含会发生什么的更多解释。
我将使用最简单的案例:A.h包括B.h和B.h包括A.h。
当您尝试编译A.obj时,预处理器会加载所有include语句,并且基本上将包含文件的剪切粘贴到源文件中(然后将结果交给编译器)。所以这是处理的顺序:
A.cpp
中,它到达#include "A.h"
,跳出A.cpp,并加载A.h A.h
中,它达到#ifndef A_H
。由于没有设定,它会继续。A.h
中,它达到#define A_H
。现在已经确定了。A.h
中,它到达#include "B.h"
,从A.h跳出,然后加载B.h B.h
中,它会到达未设置的B_H
的包含守卫并设置它。B.h
中,它到达#include "A.h"
,跳出B.h并加载A.h(再次)A.h
中,它达到#ifdef A_H
。自设置 IS 以来,它会跳过#endif
- 文件末尾。B.h
,继续预处理。因此,您可以在此处看到B.h
甚至不需要包含A.h
,因为无论如何都没有做任何事情。但如果你试图把它拿出来,那么B.obj就不会编译。当您尝试编译B.obj时,A.h
不需要包含B.h
。这导致了一个奇怪的情况:
A.obj
时,编译器将在B.h
之前的A.h
中看到声明。B.obj
时,编译器将在A.h
之前的B.h
中看到声明。为了实现这一点,必须做到两件事:
A.obj
,编译器必须能够编译B.h
而不A.h
B.obj
,编译器必须能够编译A.h
而不用B.h
因此,为了构建整个项目,A.h和B.h实际上并不能依赖于相互包容。这就是前瞻性声明的重要性发挥作用的地方。在这里您可以告诉B.h关于class A;
- 而不实际使用include语句。当然,你必须遵循前向声明的规则 - 只有引用或指针,没有解除引用。
请注意,如果添加前向声明而不删除#include
语句,则会构建项目。因为(如上所示),有时候#include
语句什么都不做。
我希望能够解决问题。
答案 1 :(得分:1)
您可以尝试添加:
class Line2;
之前的
class Circle2 {
答案 2 :(得分:0)
确保你已经#included了Line2类的定义。