By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,332 Members | 1,414 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,332 IT Pros & Developers. It's quick & easy.

Why does C++ require forward declarations?

P: n/a
This applies equally to function prototypes. Why do we have to tell the
compiler twice? Other modern compiled languages don't have this
requirement.

Just curious,

Aleko

Jul 23 '05 #1
Share this Question
Share on Google+
11 Replies


P: n/a
aleko wrote:
This applies equally to function prototypes. Why do we have to tell
the compiler twice? Other modern compiled languages don't have this
requirement.


What do you mean by "tell the compiler twice"? When you compile
a module in which the functions are only called and not defined,
what's "twice" about it?

Also, consider that C++ has conversions. If your function, like,
say, myspecialmathfunction, only takes 'double' argument, and you
provide a value of type 'int', how would the compiler know that it
has to convert your 'int' to 'double' when calling that function
unless it has a prototype (declaration) to guide it? And if the
conversion is not applied, a wrong stack frame can be formed and
the behaviour will be incorrect.

And what other languages do not have that requirement? In Pascal
you have to define all functions used *before* they are used. In
C you need to declare them as well. In Fortran... I don't know
about Fortran nowadays, it changed significantly in the decades
passed since I used it last time. Of course there are hundreds of
other languages an in some you probably don't have to declare the
function before it's used, and you probably know since you said so.

V
Jul 23 '05 #2

P: n/a

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:9N********************@comcast.com...
And what other languages do not have that requirement? In Pascal
you have to define all functions used *before* they are used. In
C you need to declare them as well. In Fortran... I don't know
about Fortran nowadays, it changed significantly in the decades
passed since I used it last time. Of course there are hundreds of
other languages an in some you probably don't have to declare the
function before it's used, and you probably know since you said so.


Neither Java nor C# have that requirement. Then again, when C++ was being
built, it was harder to write a two-pass compiler, and Java and C# are
simpler languages with simpler grammars. It's just a matter of the compiler
knowing all of the functions available before it tries to link. I mean, the
information is declared somewhere, it's just easier if the compiler only has
to look earlier in a translation unit to find a declaration.

- JFA1
Jul 23 '05 #3

P: n/a
It allows the compiler to be a "one pass" compiler. Java and C#
presumably need to read through each input file twice: once to get the
function and method names and once to do the actual compilation.

Note that the compiler needs to know the exact type of the function's
arguments that will be called in order to type check and generate the
appropriate conversions (for instance, int to double promotions) when
they are called. In other words, the compiler needs to know the
signature of the function at the call sites, so it either needs to have
a forward declaration or have read through the rest of the file
already.

(This is not strictly true; it's probably possible to generate a one
pass compiler that will work, but it would require storing the location
of all call sites so that it could go back and insert the proper code.
But this'd be difficult.)

I don't know if compiler implementation difficulty/speed is the
reasoning that led to this requirement, but it is at least a
substantial consequence.

Jul 23 '05 #4

P: n/a
I guess I asked more than one question. The original question, about
forward declarations is about situations like this:

struct B; // need to declare B in advance. why?

struct A
{
B* b;
};

struct B
{
....
};

My point is that the forward declaration simply tells the compiler
"I'll tell you about this later." It doesn't give it any concrete
information. It still doesn't know anything about B's structure. The
compiler should be able to insert its own "I'll need to resolve this
later" declaration upon encountering B* b; in A.

I suppose the reason for requiring not-yet declared types to be forward
declared is to make things easier for the compiler. This way, it can
parse the unit only once, without having to go back and forth looking
up types (possibly in other units). Does this make sense?

About the other languages:
Other compiled languages like C#, VB, and Delphi do not require forward
declarations.

I think the issue stems from the fact that C++ does not include type
information in the oject files it produces. This forces the compiler to
rely on header files, which essentially duplicate the function
signatures. That's what I mean by "telling the compiler twice".

Jul 23 '05 #5

P: n/a
aleko wrote:
I guess I asked more than one question. The original question, about
forward declarations is about situations like this:

struct B; // need to declare B in advance. why?
Not sure what you want to know. If you're looking for rationale for
requiring every name to be defined before it's used the first time,
then you need to ask in comp.std.c++, that's where the *reasons* for
rules of the language are discussed. If you just want to know why
compilers nowadays complain if youi don't provide a forward-declaration,
then the answer is simple: because the language Standard says that
a program that attempts to use a symbol (name, identifier) that was not
previsously declared, is ill-formed.

struct A
{
B* b;
};

struct B
{
...
};

My point is that the forward declaration simply tells the compiler
"I'll tell you about this later." It doesn't give it any concrete
information.
Oh, yes, it does. It says 'B' is a struct. It's not a function, it's
not an object, it's not a macro, it's not a template.
It still doesn't know anything about B's structure. The
compiler should be able to insert its own "I'll need to resolve this
later" declaration upon encountering B* b; in A.
By requiring the declarations to exist before the first use of any
name, the C++ compilers can be made better than other, multi-pass
compilers.
I suppose the reason for requiring not-yet declared types to be
forward declared is to make things easier for the compiler.
Yes, that's right.
This way,
it can parse the unit only once, without having to go back and forth
looking up types (possibly in other units). Does this make sense?
Absolutely.
About the other languages:
Other compiled languages like C#, VB, and Delphi do not require
forward declarations.

I think the issue stems from the fact that C++ does not include type
information in the oject files it produces. This forces the compiler
to rely on header files, which essentially duplicate the function
signatures. That's what I mean by "telling the compiler twice".


It doesn't duplicate anything. You declare your function once, in the
header or directly in the source. Then you use it. There is no "twice"
there anywhere. The function does not have to be defined in the same
translation unit, and that's what's great about C++. I don't have to
recompile all my units if I change the implementation and do not change
the interface because the modules that call my function do not care how
it's implemented. They only need to know the declaration (name, return
value type, and arguments).

V
Jul 23 '05 #6

P: n/a
Victor Bazarov wrote:
aleko wrote:
I guess I asked more than one question. The original question, about
forward declarations is about situations like this:

struct B; // need to declare B in advance. why?

Not sure what you want to know. If you're looking for rationale for
requiring every name to be defined before it's used the first time,
then you need to ask in comp.std.c++, that's where the *reasons* for
rules of the language are discussed. If you just want to know why
compilers nowadays complain if youi don't provide a forward-declaration,
then the answer is simple: because the language Standard says that
a program that attempts to use a symbol (name, identifier) that was not
previsously declared, is ill-formed.

struct A
{
B* b;
};

struct B
{
...
};

My point is that the forward declaration simply tells the compiler
"I'll tell you about this later." It doesn't give it any concrete
information.

Oh, yes, it does. It says 'B' is a struct. It's not a function, it's
not an object, it's not a macro, it's not a template.


I'd guess that Aleko was referring to the forward declaration not giving
anything other than the type name 'B' and that its a Struct. It
certainly doesn't give any info on B's contents (functions, etc).
It still doesn't know anything about B's structure. The
compiler should be able to insert its own "I'll need to resolve this
later" declaration upon encountering B* b; in A.

By requiring the declarations to exist before the first use of any
name, the C++ compilers can be made better than other, multi-pass
compilers.

I suppose the reason for requiring not-yet declared types to be
forward declared is to make things easier for the compiler.

Yes, that's right.


And easier for the developer. Because we don't have to include B's
header file, the compiler won't bother to see if it needs to re-compile
A should we change B. This reduces the compile time coupling between A
and B, thereby speeding up the build time.

Forward declarations should be used when ever a class does not refer to
another class by value, or use the other class inside an inlined function.

e.g.

Not needed:

class A {
...

B* b;
B& anotherB;
}
Needed:

class A {
...

B* b = new B;
}
Jul 23 '05 #7

P: n/a
Victor Bazarov wrote:
And what other languages do not have that requirement? In Pascal
you have to define all functions used *before* they are used. In
C you need to declare them as well. In Fortran... I don't know
about Fortran nowadays, it changed significantly in the decades
passed since I used it last time. Of course there are hundreds of
other languages an in some you probably don't have to declare the
function before it's used, and you probably know since you said so.


In Fortran, if type of a variable or function is not declared, it is
inferred from the first letter, unless the "implicit none" statement is
used, in which case all variables and functions must be declared. Most
Fortran experts agree that all codes should use implicit none.

Fortran 77 did not have function prototypes. Compilers often did not
warn about calling functions and subroutines with mismatched arguments
(although it was not legal Fortran), and one would get unpredictable
results.

In Fortran 90 and later versions, one can use MODULEs to get interface
checking. If file foo.f90 contains

module foo_mod
contains
function foo(x) result(xfoo)
real :: x
real :: xfoo
xfoo = 2*x
end function foo
end module foo_mod

and xfoo.f90 contains

program xmain
use foo_mod, only: foo
integer :: i=2
print*,foo(i)
end program xmain

the error of calling function foo with an integer rather than a real
argument will be detected at compile time, even if foo.f90 and xfoo.f90
are compiled separately. What most compilers do is to create a module
file foo.mod containing information about the procedures in foo.f90
when it is compiled, and this information is used to detect problems
with procedure calls. I think it works pretty well -- one gets
compile-time checking without the need for manually created header
files.

Jul 23 '05 #8

P: n/a
On Sat, 2 Apr 2005 12:23:48 -0600, James Aguilar <jf**@cec.wustl.edu>
wrote:

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:9N********************@comcast.com...
And what other languages do not have that requirement? In Pascal
you have to define all functions used *before* they are used. In
C you need to declare them as well. In Fortran... I don't know
about Fortran nowadays, it changed significantly in the decades
passed since I used it last time. Of course there are hundreds of
other languages an in some you probably don't have to declare the
function before it's used, and you probably know since you said so.


Neither Java nor C# have that requirement. Then again, when C++ was
being
built, it was harder to write a two-pass compiler, and Java and C# are
simpler languages with simpler grammars. It's just a matter of the
compiler
knowing all of the functions available before it tries to link. I mean,
the
information is declared somewhere, it's just easier if the compiler only
has
to look earlier in a translation unit to find a declaration.

- JFA1

Neither Java nor C# do not produce binary code, but intermediate
byte code. They are not real compilers but just preparing code
for real time translating (through virtual machine Java or .NET)
Jul 23 '05 #9

P: n/a
* aleko:
This applies equally to function prototypes. Why do we have to tell the
compiler twice? Other modern compiled languages don't have this
requirement.


There are two main reasons.

One, as others have mentioned, is that it makes the compiler's job easier,
and also in some cases makes the knowledgeable programmer's job easier
(the comments about "one-pass" should however be disregarded: that was
an original issue but it's not really meaningful today).

Another is that C++, sadly, lacks support for modular programming. That
is, in standard C++ you can't drag in _compiled_ declarations of something via
some 'import' or 'using' directive. So all that the compiler needs to know
must be supplied as program text.

Given that the language is as it is, though, programmers have found other uses
for declared functions that are actually not implemented anywhere.

One example is to disallow copying objects by declaring a private copy
constructor and assignment operator, another is a declared function that's
only used in sizeof expressions in template-based programming.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 23 '05 #10

P: n/a
Forward declarations can simplify header file include handling.

The following article explains this:
http://www.eventhelix.com/RealtimeMa...dePatterns.htm

Deepa
--
EventStudio 2.5 - http://www.EventHelix.com/EventStudio
Enter model in plain text;generate sequence diagram in PDF/Word

Jul 23 '05 #11

P: n/a
Taras wrote:
Neither Java nor C# do not produce binary code, but intermediate
byte code.


Neither Java nor C# produce anything. It's the compilers/linkers that do,
and so the type of code that is generated depends on the compiler you use.
The GNU Compiler Colleciton e.g. contains a Java compiler (gcj) that
generates native binary code from Java sources.

Jul 23 '05 #12

This discussion thread is closed

Replies have been disabled for this discussion.