Search

2.7 — Forward declarations and definitions

Take a look at this seemingly innocent sample program:

You would expect this program to produce the result:

The sum of 3 and 4 is: 7

But in fact, it doesn’t compile at all! Visual Studio produces the following compile error:

add.cpp(5) : error C3861: 'add': identifier not found

The reason this program doesn’t compile is because the compiler compiles the contents of code files sequentially. When the compiler reaches the function call to add on line 5 of main, it doesn’t know what add is, because we haven’t defined add until line 9! That produces the error, identifier not found.

Older versions of Visual Studio would produce an additional error:

add.cpp(9) : error C2365: 'add' : redefinition; previous definition was 'formerly unknown identifier'

This is somewhat misleading, given that add wasn’t ever defined in the first place. Despite the redundancy of the second error message, it’s useful to note that it is fairly common for a single error to produce (often redundant) multiple compiler errors or warnings.

Best practice

When addressing compile errors in your programs, always resolve the first error produced first and then compile again.

To fix this problem, we need to address the fact that the compiler doesn’t know what add is. There are two common ways to address the issue.

Option 1: Reorder the function calls

One way to address the issue is to reorder the function calls so add is defined before main:

That way, by the time main calls add, the compiler will already know what add is. Because this is such a simple program, this change is relatively easy to do. However, in a larger program, it can be tedious trying to figure out which functions call which other functions (and in what order) so they can be declared sequentially.

Furthermore, this option is not always possible. Let’s say we’re writing a program that has two functions A and B. If function A calls function B, and function B calls function A, then there’s no way to order the functions in a way that will make the compiler happy. If you define A first, the compiler will complain it doesn’t know what B is. If you define B first, the compiler will complain that it doesn’t know what A is.

Option 2: Use a forward declaration

We can also fix this by using a forward declaration.

A forward declaration allows us to tell the compiler about the existence of an identifier before actually defining the identifier.

In the case of functions, this allows us to tell the compiler about the existence of a function before we define the function’s body. This way, when the compiler encounters a call to the function, it’ll understand that we’re making a function call, and can check to ensure we’re calling the function correctly, even if it doesn’t yet know how or where the function is defined.

To write a forward declaration for a function, we use a declaration statement called a function prototype. The function prototype consists of the function’s return type, name, parameters, but no function body (the curly braces and everything in between them), terminated with a semicolon.

Here’s a function prototype for the add function:

Now, here’s our original program that didn’t compile, using a function prototype as a forward declaration for function add:

Now when the compiler reaches the call to add in main, it will know what add looks like (a function that takes two integer parameters and returns an integer), and it won’t complain.

It is worth noting that function prototypes do not need to specify the names of the parameters. In the above code, you can also forward declare your function like this:

However, we prefer to name our parameters (using the same names as the actual function), because it allows you to understand what the function parameters are just by looking at the prototype. Otherwise, you’ll have to locate the function definition.

Best practice

When defining function prototypes, keep the parameter names. You can easily create forward declarations by using copy/paste on your function declaration. Don’t forget the semicolon on the end.

Forgetting the function body

New programmers often wonder what happens if forward declare a function but do not define it.

The answer is: it depends. If a forward declaration is made, but the function is never called, the program will compile and run fine. However, if a forward declaration is made and the function is called, but the program never defines the function, the program will compile okay, but the linker will complain that it can’t resolve the function call.

Consider the following program:

In this program, we forward declare add, and we call add, but we never define add anywhere. When we try and compile this program, Visual Studio produces the following message:

Compiling...
add.cpp
Linking...
add.obj : error LNK2001: unresolved external symbol "int __cdecl add(int,int)" (?add@@YAHHH@Z)
add.exe : fatal error LNK1120: 1 unresolved externals

As you can see, the program compiled okay, but it failed at the link stage because int add(int, int) was never defined.

Other types of forward declarations

Forward declarations are most often used with functions. However, forward declarations can also be used with other identifiers in C++, such as variables and user-defined types. Variables and user-defined types have a different syntax for forward declaration, so we’ll cover these in future lessons.

Declarations vs. definitions

In C++, you’ll often hear the words “declaration” and “definition” used, often interchangeably. What do they mean? You now have enough of a framework to understand the difference between the two.

A definition actually implements (for functions or types) or instantiates (for variables) the identifier. Here are some examples of definitions:

A definition is needed to satisfy the linker. If you use an identifier without providing a definition, the linker will error.

The one definition rule (or ODR for short) is a well-known rule in C++. The ODR has three parts:

  1. Within a given file, a function, object, type, or template can only have one definition.
  2. Within a given program, an object or normal function can only have one definition. This distinction is made because programs can have more than one file (we’ll cover this in the next lesson).
  3. Within a given program, types, template functions, and inline functions can have multiple definitions so long as they are identical. We haven’t covered what most of these things are yet, so don’t worry about this for now -- we’ll bring it back up when it’s relevant.

Violating part 1 of the ODR will cause a compile to issue a redefinition error. Violating ODR parts 2 or 3 will cause the linker to issue a redefinition error. Here’s an example of a violation of part 1:

Because the above program violates ODR part 1, this causes the Visual Studio compiler to issue the following compile errors:

project3.cpp(9): error C2084: function 'int add(int,int)' already has a body
project3.cpp(3): note: see previous definition of 'add'
project3.cpp(16): error C2086: 'int x': redefinition
project3.cpp(15): note: see declaration of 'x'

A declaration is a statement that tells the compiler about the existence of an identifier and its type information. Here are some examples of declarations:

A declaration is all that is needed to satisfy the compiler. This is why we can use a forward declaration to tell the compiler about an identifier that isn’t actually defined until later.

In C++, all definitions also serve as declarations. This is why int x appears in our examples for both definitions and declarations. Since int x is a definition, it’s a declaration too. In most cases, a definition serves our purposes, as it satisfies both the compiler and linker. We only need to provide an explicit declaration when we want to use an identifier before it has been defined.

While it is true that all definitions are declarations, the converse is not true: all declarations are not definitions. An example of this is the function prototype -- it satisfies the compiler, but not the linker. These declarations that aren’t definitions are called pure declarations. Other types of pure declarations include forward declarations for variables and type declarations (you will encounter these in future lessons, no need to worry about them now).

The ODR doesn’t apply to pure declarations (it’s the one definition rule, not the one declaration rule), so you can have as many pure declarations for an identifier as you desire (although having more than one is redundant).

Author's note

In common language, the term “declaration” is typically used to mean “a pure declaration”, and “definition” is used to mean “a definition that also serves as a declaration”. Thus, we’d typically call int x; a definition, even though it both a definition and a declaration.

Quiz time

Question #1

What is a function prototype?

Show Solution

Question #2

What is a forward declaration?

Show Solution

Question #3

How do we declare a forward declaration for functions?

Show Solution

Question #4

Write the function prototype for this function (use the preferred form with names):

Show Solution

Question #5

For each of the following programs, state whether they fail to compile, fail to link, or compile and link. If you are not sure, try compiling them!

a)

Show Solution

b)

Show Solution

c)

Show Solution

d)

Show Solution


2.8 -- Programs with multiple code files
Index
2.6 -- Whitespace and basic formatting

118 comments to 2.7 — Forward declarations and definitions

  • Steven

    Love the tutorials,
    It says to declare a function you don't need to define it. Then in the definition for function prototype it's a "declaration of a function that includes the function’s name, parameters, and return type"

    But when I try to compile

     int add(); <b> int main(){... cout << add(2,3)}<b> int add(int x, int y){ return x + y;} 

    It tells me add() can't take 2 arguments, and forces me to declare

    int add(int x, int y)

    at the beginning before it will compile/work. Wouldn't that be a declaration WITH a function prototype? or should

    add();

    work at the beginning and I'm doing something wrong.

    • Alex

      Your forward declaration of add has no parameters, but your definition of add has two. There's a mismatch there that's causing the problem. Fix the forward declaration so it has two parameters.

  • Anders Melen

    This tutorial is Perfect! Thank you so much for taking the time to help others learn a new great programming language! This could surly being published!, but thanks for making it available to all!

  • That was exactly what i needed ! Thank you for your support ! =)

  • StelStav

    Hi all,

    I would like to ask what is the reasoning of c++ creators for forward declaration? Why isn’t the compiler designed in such a manner so as to look for a function definition regardless of it being before or after the actual function calling?
    I would imagine that it is enough that the function definition resided in the same scope of the function call.
    Would the above (my) logic effect the efficiency of the executable or just the compilation?

    Thanks in advance

    very nice site btw, good job admins :)

    • Alex

      C++ was developed a long time ago when computers were slow and memory was expensive. I suspect this limitation was done for efficiency/simplicity, so the compiler doesn't have to parse the file more than once, or maintain memory-intensive lookup tables for all function calls.

      More modern languages (like C#) allow you to declare functions in any order without forward declarations. It's unfortunate that C++ hasn't added this.

  • tcp

    okay so sometimes when i get to

    int add(int x, int y);
    {
    return x + y;
    }

    the little dropdown-menu-checkbox doesn't appear. why is this? the little alert box to the left of the code is green, so it's not registering as a problem, but it refuses to run the program unless int add is a dropdown item. (the code is perfect, the only difference between the site's code and my own is the dropdown box).

    the error message:

    error C2447: '{' : missing function header (old-style formal list?)

    • Auge

      Lets have a look at your code:

      int add(int x, int y);
      {
      return x + y;
      }
      

      The semicolon after the function header must be dropped:

      int add(int x, int y)
      

      The error message tells you that the compiler doesn't recognize to which function the part within the curly brackets belongs to.
      That's also because of the semicolon after the function header.

  • Its very great tutorial , it's helpful and very good.
    thank you for putting together this wonderful lessons.

  • This is lone of the pernicious effects of affirmative action. In our PC/affirmative effectiveness enlightenment, we nurse to spy the achievements and promotions of minorities as a consequence of affirmative affray policies in lieu of of distinct diligence and talent. This undermines these remarkably achievements.
    Another ungovernable here is that it sets human morality at odds with the higher heavenly morality. If the higher decency is common to adjudicator the Mass murder, necessary disease outbreaks, etc, as effects, while forgiving propriety will judge them miasmic, then the 'proficient' in each of these moralities are different. Admissible on the higher morality is not what we mean around good.

  • [url=http://drugpills.net/cialis.html][size=20][color=red][b]BILLIG CIALIS KAUFEN ONLINE[/b][/color][/size][/url]

    [url=http://drugpills.net/cialis.html][img]http://drugpills.net/img/cialis1.gif[/img][/url]

    [url=http://drugpills.net/cialis.html][size=20][b][color=blue]BILLIG CIALIS KAUFEN[/color]

    [color=red]*** Jetzt Kaufen! ***[/color]

    [color=green]CIALIS KAUFEN ONLINE[/color][/b][/size][/url]

    [url=http://drugpills.net/cialis.html]Cialis Tadalafil Aus Indien
    [/url]
    [url=http://drugpills.net/cialis.html]Erektile Dysfunktion Cialis
    [/url]
    [url=http://drugpills.net/cialis.html]Besser Cialis Levitra Viagra, Die
    [/url]
    [url=http://drugpills.net/cialis.html]Kanada Cialis Online
    [/url]
    [url=http://drugpills.net/cialis.html]Cialis Dosis
    [/url]
    Cialis Gnc
    Cialic Bestellen
    Rabatt Cialis Levitra Viagra
    Cialis Soft
    Naturlichen Cialis
    Cialis In Hohen Blutdruck Pressur
    Cialis Droge Impotenz
    Cialis Und Taub Bein
    Wie Ist Cialis Zur Behandlung Von Herz-Probleme Bei Frauen
    Viagra Cialis Und Drogen
    Ist Die Bestellung Cialis Rechtlichen
    Apotheken On Line Cialis
    Billig Europaischen Cialis
    Cialic Kaufen
    Viagra Finden Suche 76k Cialis Websites Online Kostenlos Charles
    Fakten Uber Cialis
    Cialis Jeden Tag
    Cialis Und Diabetes
    Cialis Dreampharmaceuticals
    Cialis Gelee

    [i]Finden Cialis
    Tadalafil Cialis Oder
    Cialis Sales Uk
    Verschreibungspflichtige Medikamente Viagra Cialis Propecia Mann Gesundheit
    Cialis Tijuana
    Generika Cialis Nexium Rabatt
    Lilie Lcos Cialis
    Cialis Kanada Rx
    Cialis Frauen
    Cialis Rx
    Cialis Online-Verkauf
    Indien Cialis
    Rezept Fur Cialis Kaufen
    Kaufen Viagra Cialis Levitra
    Uprima Cialis Viagra
    Besten Preis Auf Cialis
    Medikamente Wie Viargra Und Cialis
    Viagra Cialis Vs Foren
    Ubernachtung Lieferung Cialis
    Frei Cialis Ohne Rezept
    [/i]
    [u]Tadalis Edegra Generic Cialis
    Kauf Cialis Online
    Sie Cialis In Einer Apotheke
    Kapsel Cialis
    Kaufen Preiswerten Cialic
    Viagra Cialis Vs
    Online Cialis Traum Pharma -
    Kaufen Besten K Cialis Gujpkr
    Surfen Zu Kaufen Cialis Online-Link
    Cialis Levitra Oder
    Cialis V S Viagra
    Softtabs Cialis
    Cialis 20
    Generic Cialis Uberprufung
    Wirkstoff Cialis
    Wie Kommen Sie An Kostenlose Proben Von Cialis
    Cialis Rechtsanwalt
    Caverta Cialis Billig
    Cialis Maximalen Dosis
    Schlagworter Avodart Cialis Clomid Diflucan Dostinex Glucophage
    [/u]
    [b]Online-Rezept Fur Cialis
    Generic Cialis Tadalafil
    Niedrigsten Preise Cialis
    Cialis Patch
    Cialic Ohne Rezept Bestellen
    Cialis Erektion Gesundheit Mann Penis Viagra
    Apotheke Cialis Silagra Cumwithuscom
    Cialis Schuldenkonsolidierung
    Viagra Edinburgh Seiten Suche Finden Kaufen Cialis
    Avodart Cialis Clomid Diflucan Dostinex Gluco
    Xanax Viagra Cialis Porn Rolex Gru?E Sturm Beta-Jahre
    Cialis Cialis Forum Apotheke
    Billige Marke Cialis
    Cialis Ambien
    Cialis, Wo
    Flussigkeit Cialis Ordnungsgema?E Dosges
    Cialis Und Viagra Forum
    Keine Verschreibung Notwendig Cialis
    Kostenlos Viagra Cialis Levitra Prozess Bietet
    Cialis Genuinerx Net Viagra Viagra Viagra
    [/b]

  • Jeno

    Hi,

    Thanks for this wonderful website!!!

    I wrote the following code, it compiles, links and executes well, but it seems like the Return Value is wrong:

    
    // Preprocessor statement
    #include <iostream>
    
    
    //"Getem" Forward Declaration
    int Getem(int one, int two, int three, int four);
    
    
    //"Main" function declaration
    int main()
    {
    	using namespace std; {
    		std::cout<< Getem(7, 8, 3, 7)<<endl;
    	}
    	return 0;
    }
    
    int Getem(int one, int two, int three, int four)
    {
    	return one + two - three * four;
    }
    
    

    The output return value I get is -6, but when I compute the numbers myself it is a wrong calculation.

    What Am I missing?

    • Michael B

      Order of Operations.

      PEMDAS is it?

    • Ireul

      Sorry for disrespectful comment, but you miss grade school math classes.

      7 + 8 - 3 * 7 = 15 - 21 = -6, the answer given by output is perfectly correct.

    • Liquidcool

      Rule 1: First perform any calculations inside parentheses.
      Rule 2: Next perform all multiplications and divisions, working from left to right.
      Rule 3: Lastly, perform all additions and subtractions, working from left to right.

  • Michael O.

    Hi Alex!

    Thanks a lot for these great tutorials, they've teached me a lot (I began 2 days ago).
    I agree with comment #1, these tutorials deserve a publication! I have tried to learn C++ some times before, but all the books I ended up with were hard to understand, the language was difficult, but these tutorials are very easy to understand, so again, thanks a lot Alex!

    -Michael O.

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">