I have a class B, and I want to call members form class A. So:
我有一个B级,我想把成员称为A类。所以:
1.
//A.h
class B;
class A
{
private:
B* m_p;
};
//a.cpp
#include "B.h"
2.
// A.h
#include "B.h"
class A
{
private:
B * impl_;
};
which way is better and is this two similar when a small project with not too much dependence involves?
当一个没有太多依赖性的小项目涉及时,这两种方式是否更好?
6 个解决方案
#1
25
Your first way of doing it means that in a.h
, the existence of class B
is known, but not its definition. This limits what you can do with B
inside a.h
. For example, you can have variables of type B *
, but not variables of type B
(because for a declaration of a variable of type B
the compiler must be able to see the full definition of B
). Also, if you have variables of type B *
, you can't dereference the pointer (because for that, too, the definition of B
must be known).
你的第一种方式意味着在a.h中,B类的存在是已知的,但不是它的定义。这限制了你在a.h中用B做的事情。例如,您可以使用类型B *的变量,但不能使用类型B的变量(因为对于类型B的变量的声明,编译器必须能够看到B的完整定义)。另外,如果你有类型B *的变量,你不能取消引用指针(因为这也必须知道B的定义)。
Therefore, your second choice – which doesn't have these problems – is preferred, and this is what most people use most of the time.
因此,您的第二选择 - 没有这些问题 - 是首选,这是大多数人在大多数时间使用的。
It's only special cases in which the first method may be useful. For example:
这是第一种方法可能有用的特殊情况。例如:
- If the
.h
files include each other (but then you may get a number of further problems, also regarding include-guards; this is generally difficult and to be avoided); - If
b.h
is extremely large and complex, so you'd like to avoid including it wherever possible because it slows down the compilation process.
如果.h文件互相包含(但是你可能会遇到一些进一步的问题,也就是包含防范问题;这通常很难并且要避免);
如果b.h非常庞大且复杂,那么您希望尽可能避免包含它,因为它会降低编译过程的速度。
#2
12
Your first method is a forward declaration. Your second actually includes the class B.
你的第一种方法是前瞻性声明。你的第二个实际上包括B班。
When to use one over the other?
何时使用一个而不是另一个?
Use the first one when:
- In the definition of A, you only have a pointer to B, i.e. not a member of B.
- You never call any function of B from the definition of A. (i.e. all calls to member functions of B happen in the .cpp file where you actually implement A's member functions.)
- You expect the interface or size of class B to change frequently, but not the interface of A. This way, if B changes, only the contents of a.cpp get recompiled, but a.h (and other files that include a.h) need not change.
在A的定义中,你只有一个指向B的指针,即不是B的成员。
你永远不会从A的定义中调用B的任何函数。(即对B的成员函数的所有调用都发生在实际实现A的成员函数的.cpp文件中。)
你希望B类的接口或大小经常改变,但不是A的接口。这样,如果B改变,只有a.cpp的内容被重新编译,但啊(和其他包含啊的文件)不需要改变。
Use the second one when:
- You need to know the size of B. The compiler calculates a class's size using its class definition and the sizes of all its members. For example, if class A has a member that is of type B, then to calculate the size of A, the compiler needs to know the size of B; to know the size of B, you need to include b.h.
- You need to call functions of class B. In order to know whether you're calling functions that actually exist, the compiler needs to know class B's interface, i.e. you need to include b.h.
您需要调用类B的函数。为了知道您是否正在调用实际存在的函数,编译器需要知道B类的接口,即您需要包含b.h.
您需要知道B的大小。编译器使用其类定义及其所有成员的大小来计算类的大小。例如,如果类A具有类型B的成员,那么为了计算A的大小,编译器需要知道B的大小;要知道B的大小,你需要包含b.h.您需要调用类B的函数。为了知道您是否正在调用实际存在的函数,编译器需要知道B类的接口,即您需要包含b.h.
#3
8
Answer: 1.
Take a look at http://www.umich.edu/~eecs381/handouts/handouts.html
答案:1。看看http://www.umich.edu/~eecs381/handouts/handouts.html
C Header File Guidelines
C++ Header File Guidelines (by David Kieras, EECS Dept., University of Michigan) says:
C头文件指南C ++头文件指南(密歇根大学EECS部门David Kieras)说:
Guideline #10. If an incomplete declaration of a type X will do, use it instead of #including its header X.h. If another struct or class type X appears only as a pointer or reference type in the contents of a header file, then you should not #include X.h, but just place an incomplete declaration of X (also called a "forward" declaration) near the beginning of the header file, as in:
class X;
See the handout Incomplete Declarations for more discussion of this powerful and valuable technique. Note that the Standard library includes a header of incomplete declarations that often suffices for the<iostream>
library, named<iosfwd>
. #include<iosfwd>
whenever possible, because the<iostream>
header file is extremely large (giant templates!).准则#10。如果类型X的声明不完整,请使用它而不是#including其标题X.h.如果另一个结构或类类型X在标题文件的内容中仅作为指针或引用类型出现,那么您不应该#include Xh,而只是在X附近放置一个不完整的X声明(也称为“前向”声明)。标题文件的开头,如:X类;有关这种强大而有价值的技术的更多讨论,请参阅讲义不完整声明。请注意,标准库包含一个不完整声明的标头,通常用于
库,名为 。 #include 尽可能,因为 标题文件非常大(巨型模板!)。
#4
0
The second is better. It makes the B
class a module that you include using the .h
file. Consider the case where you subclass B
in the future and you update A
to use C
. In the second case, you only replace the header #include
and A
's make-up. In the first case, you have to change the forward declaration. Also, in the second case, you define more than just the symbol B
.
第二个更好。它使B类成为您使用.h文件包含的模块。考虑以后将子类化为B并更新A以使用C的情况。在第二种情况下,只替换标题#include和A的化妆。在第一种情况下,您必须更改前向声明。此外,在第二种情况下,您定义的不仅仅是符号B.
And as in the comments, you should use #include "B.h"
if the header file is in the same directory as the rest of the code.
如同注释一样,如果头文件与其余代码位于同一目录中,则应使用#include“B.h”。
#5
0
Well what you're doing is called forward decleration, the reason you would want that is if you had something like class A that uses class B and ALSO class B that uses class A.
那么你正在做的事情被称为前向解除,你想要的原因就是你有类似A的东西使用类B和ALSO类B使用类A.
In a case where there is only one relation you can certainly use your second choice. If you need the double usage then at least one of your classes declerations would have to use forward decleration
在只有一种关系的情况下,您当然可以使用您的第二选择。如果您需要双重用法,那么至少有一个类的变换必须使用前向变换
#6
0
Just declare the class in your class A's header.
只需在类A的标题中声明该类。
class B;
#1
25
Your first way of doing it means that in a.h
, the existence of class B
is known, but not its definition. This limits what you can do with B
inside a.h
. For example, you can have variables of type B *
, but not variables of type B
(because for a declaration of a variable of type B
the compiler must be able to see the full definition of B
). Also, if you have variables of type B *
, you can't dereference the pointer (because for that, too, the definition of B
must be known).
你的第一种方式意味着在a.h中,B类的存在是已知的,但不是它的定义。这限制了你在a.h中用B做的事情。例如,您可以使用类型B *的变量,但不能使用类型B的变量(因为对于类型B的变量的声明,编译器必须能够看到B的完整定义)。另外,如果你有类型B *的变量,你不能取消引用指针(因为这也必须知道B的定义)。
Therefore, your second choice – which doesn't have these problems – is preferred, and this is what most people use most of the time.
因此,您的第二选择 - 没有这些问题 - 是首选,这是大多数人在大多数时间使用的。
It's only special cases in which the first method may be useful. For example:
这是第一种方法可能有用的特殊情况。例如:
- If the
.h
files include each other (but then you may get a number of further problems, also regarding include-guards; this is generally difficult and to be avoided); - If
b.h
is extremely large and complex, so you'd like to avoid including it wherever possible because it slows down the compilation process.
如果.h文件互相包含(但是你可能会遇到一些进一步的问题,也就是包含防范问题;这通常很难并且要避免);
如果b.h非常庞大且复杂,那么您希望尽可能避免包含它,因为它会降低编译过程的速度。
#2
12
Your first method is a forward declaration. Your second actually includes the class B.
你的第一种方法是前瞻性声明。你的第二个实际上包括B班。
When to use one over the other?
何时使用一个而不是另一个?
Use the first one when:
- In the definition of A, you only have a pointer to B, i.e. not a member of B.
- You never call any function of B from the definition of A. (i.e. all calls to member functions of B happen in the .cpp file where you actually implement A's member functions.)
- You expect the interface or size of class B to change frequently, but not the interface of A. This way, if B changes, only the contents of a.cpp get recompiled, but a.h (and other files that include a.h) need not change.
在A的定义中,你只有一个指向B的指针,即不是B的成员。
你永远不会从A的定义中调用B的任何函数。(即对B的成员函数的所有调用都发生在实际实现A的成员函数的.cpp文件中。)
你希望B类的接口或大小经常改变,但不是A的接口。这样,如果B改变,只有a.cpp的内容被重新编译,但啊(和其他包含啊的文件)不需要改变。
Use the second one when:
- You need to know the size of B. The compiler calculates a class's size using its class definition and the sizes of all its members. For example, if class A has a member that is of type B, then to calculate the size of A, the compiler needs to know the size of B; to know the size of B, you need to include b.h.
- You need to call functions of class B. In order to know whether you're calling functions that actually exist, the compiler needs to know class B's interface, i.e. you need to include b.h.
您需要调用类B的函数。为了知道您是否正在调用实际存在的函数,编译器需要知道B类的接口,即您需要包含b.h.
您需要知道B的大小。编译器使用其类定义及其所有成员的大小来计算类的大小。例如,如果类A具有类型B的成员,那么为了计算A的大小,编译器需要知道B的大小;要知道B的大小,你需要包含b.h.您需要调用类B的函数。为了知道您是否正在调用实际存在的函数,编译器需要知道B类的接口,即您需要包含b.h.
#3
8
Answer: 1.
Take a look at http://www.umich.edu/~eecs381/handouts/handouts.html
答案:1。看看http://www.umich.edu/~eecs381/handouts/handouts.html
C Header File Guidelines
C++ Header File Guidelines (by David Kieras, EECS Dept., University of Michigan) says:
C头文件指南C ++头文件指南(密歇根大学EECS部门David Kieras)说:
Guideline #10. If an incomplete declaration of a type X will do, use it instead of #including its header X.h. If another struct or class type X appears only as a pointer or reference type in the contents of a header file, then you should not #include X.h, but just place an incomplete declaration of X (also called a "forward" declaration) near the beginning of the header file, as in:
class X;
See the handout Incomplete Declarations for more discussion of this powerful and valuable technique. Note that the Standard library includes a header of incomplete declarations that often suffices for the<iostream>
library, named<iosfwd>
. #include<iosfwd>
whenever possible, because the<iostream>
header file is extremely large (giant templates!).准则#10。如果类型X的声明不完整,请使用它而不是#including其标题X.h.如果另一个结构或类类型X在标题文件的内容中仅作为指针或引用类型出现,那么您不应该#include Xh,而只是在X附近放置一个不完整的X声明(也称为“前向”声明)。标题文件的开头,如:X类;有关这种强大而有价值的技术的更多讨论,请参阅讲义不完整声明。请注意,标准库包含一个不完整声明的标头,通常用于
库,名为 。 #include 尽可能,因为 标题文件非常大(巨型模板!)。
#4
0
The second is better. It makes the B
class a module that you include using the .h
file. Consider the case where you subclass B
in the future and you update A
to use C
. In the second case, you only replace the header #include
and A
's make-up. In the first case, you have to change the forward declaration. Also, in the second case, you define more than just the symbol B
.
第二个更好。它使B类成为您使用.h文件包含的模块。考虑以后将子类化为B并更新A以使用C的情况。在第二种情况下,只替换标题#include和A的化妆。在第一种情况下,您必须更改前向声明。此外,在第二种情况下,您定义的不仅仅是符号B.
And as in the comments, you should use #include "B.h"
if the header file is in the same directory as the rest of the code.
如同注释一样,如果头文件与其余代码位于同一目录中,则应使用#include“B.h”。
#5
0
Well what you're doing is called forward decleration, the reason you would want that is if you had something like class A that uses class B and ALSO class B that uses class A.
那么你正在做的事情被称为前向解除,你想要的原因就是你有类似A的东西使用类B和ALSO类B使用类A.
In a case where there is only one relation you can certainly use your second choice. If you need the double usage then at least one of your classes declerations would have to use forward decleration
在只有一种关系的情况下,您当然可以使用您的第二选择。如果您需要双重用法,那么至少有一个类的变换必须使用前向变换
#6
0
Just declare the class in your class A's header.
只需在类A的标题中声明该类。
class B;