什么时候声明足够,我们什么时候需要定义? [英] when are declarations sufficent and when do we need definitions?

查看:116
本文介绍了什么时候声明足够,我们什么时候需要定义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好,


有时我们在定义/声明

类(或函数?)时需要声明,但有时我们需要定义。我学会了

,如果我们定义一个类(B)有一个类(a_obj)的类

类型(A),那么我们需要定义一个A ,但如果B有一个指向

A的指针,那么我们只需要转发声明A.我被告知这是因为

编译器需要看到A的实现为a_obj分配

内存时。但是,我认为编译器在创建B类对象之前不会分配任何内存。因此,如果我有

a .cpp文件


A级;


B级{

A a_obj;

};


然后似乎可以转发声明A,因为没有对象创建了B / B
。那么在这种情况下,为什么我还要定义A(或

包含它的头文件)?


同样,我们可以转发声明如果我们只声明一个像
这样的函数
A f(A a);


但我们在定义时需要A'的实现f


A f(A a){...}


如果我的.cpp文件只有f''定义没有任何调用

f的程序,那么转发声明A是不是绝对安全?


我想我的一般问题我们什么时候可以使用没有

定义的声明?


关于前向声明的另一个问题是我们为什么要使用


A级;


而不是


外部A级;


我认为后者说A是其他地方定义的类。


非常感谢,

Jess

解决方案

Jess写道:


您好,


有时我们在定义/声明

类(或函数)时需要声明?),但有时我们需要定义。我学会了

,如果我们定义一个类(B)有一个类(a_obj)的类

类型(A),那么我们需要定义一个A ,但如果B有一个指向

A的指针,那么我们只需要转发声明A.我被告知这是因为

编译器需要看到A的实现为a_obj分配

内存时。



不,它与分配无关。它与语义有关。

经验法则是:当程序不需要知道关于

类的任何内容时,前向声明就足够了。也就是说,如果你只是
有一个指针(这是一个内存地址)给一个类,那么就没有什么需要知道这个类本身的内容。另一方面,如果你想要使用类的方法,或者如果你有一个不是

指针的成员,那么有关该类的其他信息(这样的类

维度或其成员)是必需的,并且需要定义。


问候,


Zeppe


Jess写道:


有时声明是我们定义/声明
类(或函数?),但有时我们需要定义。我学会了

,如果我们定义一个类(B)有一个类(a_obj)的类

类型(A),那么我们需要定义一个A ,但是如果B有一个指向
的指针



...或者对...的引用


A那么我们只需要转发声明A.我被告知这是因为

编译器需要在为a_obj分配

内存时看到A的实现。但是,我认为编译器在创建B类对象之前不会分配任何内存。因此,如果我有

a .cpp文件


A级;


B级{

A a_obj;

};


然后似乎可以转发声明A,因为没有对象创建了B / B
。那么在这种情况下,为什么我还要定义A(或

包含它的头文件)?



编译器需要计算B对象的大小。为此它需要知道''A''对象的大小是多少。它不知道'A''对象的大小,而不知道它包含的是什么。


同样,我们可以转发声明如果我们只声明一个像
这样的函数
A f(A a);


但我们在定义时需要A'的实现f


A f(A a){...}


如果我的.cpp文件只有f''定义没有任何调用

" f"的程序,那么转发声明A是不是绝对安全?



该标准并未禁止在函数

声明中使用不完整类型,但在定义中您不能使用不完整类型。

对于你自己的代码中没有调用的函数没有特殊规定。必须生成它们的代码,因此参数

必须有完整的类型。


>

我想我的一般问题是我们何时可以使用没有

定义的声明?



使用是什么意思?


>

关于前瞻性声明的另一个问题是,为什么我们使用


A级;


而不是


extern class A;


我认为后者说A是在其他地方定义的类。



" extern"不允许使用类声明。只有物品

和功能。


V

-

请删除资金''当用电子邮件回复时,我会回答这个问题。我不回复最热门的回复,请不要问


On 2007-06-19 13:59,Jess写道:


您好,


有时声明就是我们所需要的我们定义/声明

类(或函数?),但有时我们需要定义。我学会了

,如果我们定义一个类(B)有一个类(a_obj)的类

类型(A),那么我们需要定义一个A ,但如果B有一个指向

A的指针,那么我们只需要转发声明A.我被告知这是因为

编译器需要看到A的实现为a_obj分配

内存时。但是,我认为编译器在创建B类对象之前不会分配任何内存。因此,如果我有

a .cpp文件


A级;


B级{

A a_obj;

};


然后似乎可以转发声明A,因为没有对象创建了B / B
。那么在这种情况下,为什么我还要定义A(或

包含它的头文件)?



在创建这样的对象之前,编译器确实不会为类型B的对象分配内存。但编译器将需要知道A在定义B时的样子,因为B的定义应该包含所有编译器需要知道的能够创建的

类型B的对象。但如果编译器不知道

B定义中的A是什么,它怎么知道B是什么?
< blockquote class =post_quotes>
同样,如果我们只声明一个像
这样的函数,我们可以转发声明A.
A f(A a);


但我们在定义f时需要A'的实现


A f(A a){...}


如果我的.cpp文件只有f'的定义而没有任何调用

" f"的程序,那么转发声明A是不是完全安全?



再次,定义应该包含编译器需要的所有信息,在这种情况下它必须知道A的大小以便它可以为f()生成

的代码。如果你不使用f()一个智能编译器可能是

能够摆脱f()作为优化,但标准没有

需要它,所以一个不那么聪明的编译器必须能够编译代码



我想我的一般问题是什么时候可以我们使用没有

定义的声明?



通常这是一个大小的问题,对于许多事情(比如一个

类的成员),编译器需要知道尺寸。只要您使用指针

引用,编译器就不需要知道更多,因为

指针和引用的大小是已知的。如果你以某种方式尝试使用

指针/引用(比如调用成员函数),你需要

定义。


关于前瞻性声明的另一个问题是我们为什么要使用


A类;


而不是


外部A级;



extern用于告诉编译器有关当前编译单元中未定义的现有变量

。所以,当你写下

之类的东西,比如

extern A myA;


你告诉编译器存在一个类型A的变量名为myA。

如果是前向声明,则使用单词class; (注意

,我没有使用class在上面的extern声明中)告诉

编译器你说的是一个类型而不是一个变量。虽然一个

可以使用


外部A级;


作为前瞻性声明它不需要因为编译器没有特别关注定义类型的地方,只要它在某个地方。

另请注意,这将是一种新的用法extern,

这意味着定义在编译单元外部,

,因为在大多数情况下,前向声明后跟真实的

稍后在文件中声明或通过一些包含的文件(换句话说

前向声明和定义在同一个编译单元中),

像这样:


B级;


A级{

B * parentPtr;

/ * .. 。* /

};


B级{

一个孩子;

/ *。 .. * /

};


-

Erik Wikstr?m


Hello,

Sometimes declarations are all what we need when we define/declare
classes (or functions?), but sometimes we need definitions. I learned
that if we define a class (B) that has an object (a_obj) of a class
type (A), then we need to define A as well, but if B has a pointer to
A, then we only need to forward declare A. I was told this is because
the compiler needs to see the implemenation of A when allocating
memory for a_obj. However, I think compilers won''t allocate any
memory until we create an object of class B. Therefore, if I have
a .cpp file

class A;

class B{
A a_obj;
};

then it seems ok to forward declare A, because there''s no object of
class B created. So in this case, why do I still have to define A (or
include it''s header file)?

Similarly, we can forward declare A if we only declare a function like

A f(A a);

but we need A''s implemenation when we define "f"

A f(A a){...}

If my .cpp file only has f''s definition without any program that calls
"f", then shouldn''t it be perfectly safe to forward declare A?

I guess my general question is when can we use declarations without
definitions?

Another question about forward declaration is that why do we use

class A;

instead of

extern class A;

I think the latter says A is a class defined somewhere else.

Thanks a lot,
Jess

解决方案

Jess wrote:

Hello,

Sometimes declarations are all what we need when we define/declare
classes (or functions?), but sometimes we need definitions. I learned
that if we define a class (B) that has an object (a_obj) of a class
type (A), then we need to define A as well, but if B has a pointer to
A, then we only need to forward declare A. I was told this is because
the compiler needs to see the implemenation of A when allocating
memory for a_obj.

No, it is not related to allocation. It''s related to the semantics. The
rule of thumb is: "when the program doesn''t need to know anything about
the class, the forward declaration suffices". That is, if you merely
have a pointer (which is an address of memory) to a class, there is no
need to know anything about the class itself. On the other side, if you
want to use methods of the class, or if you have a member that is not a
pointer, additional information related to the class (such the class
dimension or its members) are required, and the definition is needed.

Regards,

Zeppe


Jess wrote:

Sometimes declarations are all what we need when we define/declare
classes (or functions?), but sometimes we need definitions. I learned
that if we define a class (B) that has an object (a_obj) of a class
type (A), then we need to define A as well, but if B has a pointer to

...or a reference to..

A, then we only need to forward declare A. I was told this is because
the compiler needs to see the implemenation of A when allocating
memory for a_obj. However, I think compilers won''t allocate any
memory until we create an object of class B. Therefore, if I have
a .cpp file

class A;

class B{
A a_obj;
};

then it seems ok to forward declare A, because there''s no object of
class B created. So in this case, why do I still have to define A (or
include it''s header file)?

The compiler needs to calculate the size of a ''B'' object. For that it
needs to know what the size of an ''A'' object is. It cannot know the
size of an ''A'' object without knowing what it consists of.

Similarly, we can forward declare A if we only declare a function like

A f(A a);

but we need A''s implemenation when we define "f"

A f(A a){...}

If my .cpp file only has f''s definition without any program that calls
"f", then shouldn''t it be perfectly safe to forward declare A?

The standard does not prohibit from incomplete types used in function
declarations, but in definitions you cannot use incomplete types. There
is no special provisions for the functions that aren''t called within
your own code. The code for them has to be generated, so the parameters
have to have complete types.

>
I guess my general question is when can we use declarations without
definitions?

What do you mean by "use"?

>
Another question about forward declaration is that why do we use

class A;

instead of

extern class A;

I think the latter says A is a class defined somewhere else.

"extern" is not allowed with a class declaration. Only with objects
and functions.

V
--
Please remove capital ''A''s when replying by e-mail
I do not respond to top-posted replies, please don''t ask


On 2007-06-19 13:59, Jess wrote:

Hello,

Sometimes declarations are all what we need when we define/declare
classes (or functions?), but sometimes we need definitions. I learned
that if we define a class (B) that has an object (a_obj) of a class
type (A), then we need to define A as well, but if B has a pointer to
A, then we only need to forward declare A. I was told this is because
the compiler needs to see the implemenation of A when allocating
memory for a_obj. However, I think compilers won''t allocate any
memory until we create an object of class B. Therefore, if I have
a .cpp file

class A;

class B{
A a_obj;
};

then it seems ok to forward declare A, because there''s no object of
class B created. So in this case, why do I still have to define A (or
include it''s header file)?

It''s true that the compiler will not allocate memory for an object of
type B until you create such an object. But the compiler will need to
know how A looks like when you define B since the definition of B should
contain all the compiler needs to know to be able to create an object of
type B. But if the compiler does not know what A is in the definition of
B, how can it know what B is?

Similarly, we can forward declare A if we only declare a function like

A f(A a);

but we need A''s implemenation when we define "f"

A f(A a){...}

If my .cpp file only has f''s definition without any program that calls
"f", then shouldn''t it be perfectly safe to forward declare A?

Once again, the definition should contain all information the compiler
need, in this case it must know the size of A so that it can generate
the code for f(). If you then don''t use f() a smart compiler might be
able get rid of f() as an optimization, but the standard does not
require it, so a not-so-smart compiler must be able to compile the code
also.

I guess my general question is when can we use declarations without
definitions?

Usually it''s a question of size, for many things (like a member of a
class) the compiler needs to know the size. As long as you use pointers
of references the compiler does not need to know more since the sizes of
pointers and references are known. If you in some way try to use a
pointer/reference (like calling a member-function) you''ll need the
definition.

Another question about forward declaration is that why do we use

class A;

instead of

extern class A;

extern is used when you tell the compiler about an existing variable
that was not defined in the current compilation unit. So when you write
something like

extern A myA;

you tell the compiler that there exists a variable of type A called myA.
In the case of forward declarations you use the word "class" (notice
that I didn''t use "class" in the above extern declaration) to tell the
compiler that you are talking about a type and not a variable. While one
could have used

extern class A;

as forward declarations it''s not needed since the compiler does not
particularly care where the type is defined, as long as it is somewhere.
Notice also that this would be a new kind of use of the word extern,
which means that the definition is external to the compilation unit,
since in most cases a forward declaration is followed by the real
declaration later in the file or by some included file (in other words
the forward declaration and definition is in the same compilation unit),
like this:

class B;

class A {
B* parentPtr;
/* ... */
};

class B {
A child;
/* ... */
};

--
Erik Wikstr?m


这篇关于什么时候声明足够,我们什么时候需要定义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆