是否有人能够解释为什么头文件有这样的东西?
class foo; // This here?
class bar
{
bar();
};
使用它时是否需要包含声明?
感谢。
答案 0 :(得分:10)
第一个class foo;
被称为类foo的forward declaration。它只是让编译器知道它存在并且它命名一个类。这使得foo被称为“不完整类型”(除非已经看到foo的完整声明)。如果类型不完整,您可以声明该类型的指针,但不能分配该类型的实例或执行任何需要知道其大小或成员的内容。
这种前向声明经常用于两个类型,每个类型可能有彼此指针,在这种情况下,两个类型都需要能够表达指向另一个类型的指针的概念,因此你将有一个循环依赖,没有这样的一个东西。这主要是因为C ++使用单一传递机制来解析类型;在Java中,您可以拥有循环依赖,而无需前向声明,因为Java使用多次传递。您还可能会看到前向声明,其中作者误以为使用前向声明而不是包含所需的标头会缩短编译时间;当然,情况并非如此,因为你需要包含完整的声明(即标题),如果使用预处理器保护,那么编译时间基本没有区别。
要回答关于是否需要包含的问题...假设您只需要部分类型,那么您的标题不需要直接包含已向前声明的类型的标题;但是,无论谁使用你的标题,当他们使用你的类型时,都需要包含前向声明类型的标题,所以你也可以只包括另一个标题。
答案 1 :(得分:2)
那是forward declaration。例如,如果类栏具有指向foo对象的指针,但您不想立即包含foo对象的整个定义,则需要它。
答案 2 :(得分:1)
这是该课程的前瞻性声明。 根据我的经验,这通常在您具有循环依赖时完成...例如
in foo.h
--------
#include "bar.h"
class foo
{
public:
foo(bar *bar);
private:
foo *m_foo;
};
and in bar.h
------------
class foo;
class bar
{
public:
void methodFooWillCall();
protected:
std::list<foo *> myFoos;
}
答案 3 :(得分:1)
好奇的是,为什么我们需要前向声明一词呢?前向声明不仅仅是声明(而不是定义)吗?
class X; // declaration
class X // definition
{
int member;
void function();
};
答案 4 :(得分:0)
这是一份前瞻性声明。请考虑以下示例:
class foo; // you likely need this for the code beneath to compile
class bar {
void smth( foo& );
};
如果你没有包含class foo
的定义,编译器在编译class bar
的定义之前就会看到它,那么代码将无法编译(编译器会说它没有知道foo
的意思),除非你有前瞻声明。
答案 5 :(得分:0)
这是“foo”类的前向声明。它允许您声明指针和对类的引用,但不能使用它(例如调用成员或确定其大小),因为它尚未定义!之后必须进行完整,正常的声明(class foo { ... };
)。
这对于声明两个彼此保持指针的类很有用,否则将无法设置。
答案 6 :(得分:0)
这称为前向声明。类foo
的主体将在文件的后面部分定义。前向声明是为了解决循环依赖:类Bar的定义需要类Foo,反之亦然。
class Bar
{
Foo * foo;
};
class Foo
{
Bar * bar;
};
如您所见,Bar
引用了Foo
,反之亦然。如果您尝试编译它,编译器会投诉说它对Foo
一无所知。解决方案是在class Foo
之上转发声明Bar
(就像你在main
之上声明一个函数的原型并稍后定义它的主体一样。)
class Foo; //Tells the compiler that there is a class Foo coming down the line.
class Bar
{
Foo * foo;
};
class Foo
{
Bar * bar;
};
答案 7 :(得分:0)
这称为前瞻性声明。它用于使您的代码知道类foo存在。这反过来可以由类栏使用。
它常用于解决循环问题。以此为例
//a.h
#include "b.h"
class A
{
void useB(B obj);
}
和
// b.h
#include "a.h"
class B
{
void useA(A obj);
}
这导致循环包含问题,因为a.h包括b.h,其又包括a.h到无穷大。您可以通过在每个标头中对每个类进行前向声明来解决此问题,如下所示:
//a.h
class B;
class A
{
void useB(B obj);
}
// b.h
class A;
class B
{
void useA(A obj);
}
注意:当您遇到循环包含问题时,通常会出现概念/建模问题。在尝试使用前向声明解决问题之前,您应该问自己,您的类是否已经定义好。
答案 8 :(得分:0)
试着想一想这个:
文件bar.h:
#include "bar.h"
class Foo
{
Bar* bar_ptr;
}
file foo.h:
#include "foo.h"
class Bar
{
Foo* foo_ptr;
}
这不起作用,首先是由于无限的#include链,然后如果你摆脱其中一个包含,要么Foo不知道Bar是什么,或者Bar不会知道Foo是什么。
请改为尝试:
class Bar;
class Foo
{
Bar* bar_ptr;
};
file foo.h:
class Foo;
class Bar
{
Foo* foo_ptr;
};