473,377 Members | 1,151 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,377 software developers and data experts.

Why does C++ require forward declarations?

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
11 2401
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

"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
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
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
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
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
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
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
* 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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: Alan Lee | last post by:
Hi i am writing a small simulation for a bunch of atoms jumping around on a surface. I know i am a crappy programmer since i am not very familiar with object oriented languages. I am woindering...
6
by: Steven T. Hatton | last post by:
Should I be able to forward declare something from a namespace different from the current one? For example the following code compiles: //testdriver.hpp #ifndef TESTDRIVER_HPP #define...
5
by: John Gabriele | last post by:
I'm hoping someone can please help me remember the C++ rule: When you're writing a header file for a class (say, some_namespace::Bar), and that class makes use of another class...
20
by: Steven T. Hatton | last post by:
I just read this in the description of how C++ is supposed to be implemented: "All external object and function references are resolved. Library components are linked to satisfy external...
2
by: Neo | last post by:
Hi, I am new to C++ and want to know what are forward declarations and any site which has a good introductory explanation. thanks in advance, nick
12
by: fox | last post by:
How do I (portably) make a forward reference to a static (I mean file-scope) variable? I've been using "extern" for years, for example: extern int x; int foo(void) { return x++; }
2
by: Carlos Martinez Garcia | last post by:
Hi all: I usually make forward declarations in headers. Something like this: class MyClass; Now, I need a reference to a type defined like this (traditional C Style): typedef struct {
6
by: Hunk | last post by:
Hi I have a question on usage of forward declarations of templates. While searching through this group , people suggested using forward declarations and typedefs for templates as // in...
0
by: Rune Allnor | last post by:
Hi all. I have these classes, implemented as templates in header files. Right now I have one file per class, where both the declarations and implementations of one class are located in each...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.