C++ Projects and Linkage |
|
A computer application is primarily a series of files put together to compose a single entity. With previous generations of programming, you had to create text files, save them with a .c, a .cc, or a .cpp extension, link them and compile them. Many modern programming environments allow you to create the files and hand them to the compiler that would link them as a project, and then create an executable. In reality, the process has not changed, it has only been made easier and faster. Still, because the programming environments are developed by different companies, each presents its own way of creating the necessary files, compiling them, and creating an executable. When writing a program, the main reason for using functions is to isolate assignments. This allows you to effectively troubleshoot problems when they arise (because they will arise, not if but when). For example, if you are asked to write a program that would process orders at a department store, you can write one long main() function that would process all requests and orders. When the store is having a sale and you need to apply a discount to the program, you would spend time looking for the sections that use the discount and calculate the price. If you use functions to isolate assignments, you can easily find out which particular function deals with discount; all you would have to do is change the discount value without having to read the whole program.
When using functions in a program, we found out that the order of declaring functions was important. For example, you cannot call a function that has not been declared yet. For this reason, whenever you need to call a function, you should find out where it was created or whether it has been declared already. If the program is using many functions, it would become cumbersome to start looking for functions. At the same time, on a large program, it is usual for many functions to use the same kind of variable. Although you can locally declare the same variable needed by a function, if these functions of the same program would need to exchange values among them, you should declare some variables globally, usually on top of the file, then make such a variable available to any function that needs it. To make these functions and variables easily manageable, you can create one file where you would list the functions and variables used in a program. Such a file is called a header file and it has the h extension.
As you are creating header files, if you work with a large team, you should avoid including in your program a file that has already been included. C++ allows you to avoid this by asking the compiler to check whether a header or a section of code has already been included in your program. This checking is performed using objects called preprocessors. When using preprocessors to check whether a section of code or a file has already been included in your program, you start the file or the section with #ifndef WhatToCheck The preprocessors must start with the # symbol as we have been using on the #include preprocessor so far. The ifndef preprocessor, word for word, means If Not Defined. It refers to the word on its right side to check if that word has already been included. Because the #ifndef is used to check If WhatToCheck has not been defined yet, it can also be written as #if !define WhatToCheck Both would mean the same. In reality, what you would be asking this preprocessor to do is to check if the WhatToCheck word has not already been included. If it has not, then you would ask the compiler to define this section of code with the WhatToCheck word. To do this, you would decide that the section of code you want to delimit will be referred to with the WhatToCheck word. Therefore, the #ifndef preprocessor is followed by a #define WhatToCheck This means that if WhatToCheck has not been included yet, then it would be defined starting with the #define. The section must end with the #endif preprocessor. This time, you do not need to specify what needs to be ended; the compiler will figure that out.
After creating the header file, you can create another file to define the functions. The file used to implement the functions of the header file is called the Source File and it has a cpp extension. In order to use the code that is written in the header file, you must specify its file using the #include preprocessor and including the name of the file in double-quotes. The process of creating header and source files depends on your programming environment.
|
|
Practical Learning: Creating a Header File: Borland C++BuilderX |
Practical Learning: Creating a Header File: Borland C++ Builder 6 |
|
Practical Learning: Creating a Header File: Microsoft Visual C++ |
|
Practical Learning: Creating a Header File: Dev-C++ |
|
Practical Learning: Creating a Header File: Microsoft Visual C++ .Net |
|
#ifndef _INERTIA_H_ #define _INERTIA_H_ double MomentOfInertia(const double b, const double h); double MomentOfInertia(const double R); double MomentOfInertia(const double b, const double h, const int); double GetBase(); double GetHeight(); double GetRadius(); #endif // INERTIA_H_ |
Source Files |
A source file is used to actually define the behavior
of an object. This is also referred to as implementing the object. |
Practical Learning: Creating a Source File: Borland C++ BuilderX |
Practical Learning: Creating a Source File: KDevelop |
|
Practical Learning: Creating a Source File: Borland C++ Builder |
|
Practical Learning: Creating a Source File: Microsoft Visual C++ |
|
Practical Learning: Creating a Source File: Dev-C++ |
|
Practical Learning: Creating a Source File: Microsoft Visual C++ .Net |
|
#include <iostream> using namespace std; #include "Inertia.h" // Rectangle double MomentOfInertia(const double b, const double h) { return b * h * h * h / 3; } // Semi-Circle double MomentOfInertia(const double r) { const double PI = 3.14159; return r * r * r * r * PI/ 8; } // Triangle double MomentOfInertia(const double b, const double h, const int) { return b * h * h * h / 12; } double GetBase() { double b; cout << "Base: "; cin >> b; return b; } double GetHeight() { double h; cout << "Height: "; cin >> h; return h; } double GetRadius() { double r; cout << "Radius: "; cin >> r; return r; } |
#include <iostream> #include <string> using namespace std; #include "Inertia.h" void Announce(const string Figure) { cout << "Enter the dimensions of the " << Figure << "\n"; } int main() { double Length, Height, Radius; Announce("rectangle"); Length = GetBase(); Height = GetHeight(); cout << "Rectangle\n" << "Moment of inertia with regard to the X axis: "; cout << "I = " << MomentOfInertia(Length, Height) << "mm\n\n"; Announce("semi-circle"); Radius = GetRadius(); cout << "Semi-Circle\n" << "Moment of inertia with regard to the X axis: "; cout << "I = " << MomentOfInertia(Radius) << "mm\n\n"; Announce("triangle"); Length = GetBase(); Height = GetHeight(); cout << "\nTriangle\n" << "Moment of inertia with regard to the X axis: "; cout << "I = " << MomentOfInertia(Length, Height, 1) << "mm\n"; return 0; } |
Variable External Linkage |
We saw that you could use different files in the same program. In our header files, we declared only functions. In many cases, you can also declare one or more variables in a (header) file and want to access such a variable in another file. After declaring a variable in one file, you can access it in any other file. This process is referred to as external linkage. To perform external linkage with a variable, in most cases, there is not much to do: you simply declare and optionally initialize a variable in one file, #include that file in another file, and use the variable as you see fit. Consider the following example: |
Header File: Exercise.h |
#ifndef Exercise_H #define Exercise_H int numberOfPagesInTheBook = 842; #endif // Exercise_H |
Source File: Exercise.cpp |
#ifdef __BORLANDC__ #pragma argsused #endif #include <iostream> #include "Exercise.h" using namespace std; int main( int argc, char * argv[] ) { cout << "This book contains " << numberOfPagesInTheBook << " pages"; return 0; } |
This would produce: This book contains 842 pages Imagine that, before accessing such a variable, you declare another variable of the same data type and the same name. Consider the following example: |
Header File: Exercise.h |
#ifndef Exercise_H #define Exercise_H int numberOfPagesInTheBook = 842; #endif // Exercise_H |
Source File: Exercise.cpp |
#ifdef __BORLANDC__ #pragma argsused #endif #include <iostream> #include "Exercise.h" using namespace std; int main( int argc, char * argv[] ) { int numberOfPagesInTheBook; cout << "This book contains " << numberOfPagesInTheBook << " pages"; return 0; } |
Since a file included, in this case Exercise.h, has a variable with the same name as a locally declared variable, when you try accessing it locally, the compiler would consider the local variable and would ignore the external variable. The above code would produce: This book contains 8856072 pages (This result is from Borland C++BuilderX) To indicate that the newly declared variable is simply a reference to the external variable, when re-declaring it, start the declaration with the extern keyword: #ifdef __BORLANDC__ #pragma argsused #endif #include <iostream> #include "Exercise.h" using namespace std; int main( int argc, char * argv[] ) { extern int numberOfPagesInTheBook; cout << "This book contains " << numberOfPagesInTheBook << " pages"; return 0; } This time, it is the external variable that will be accessed. |
References |
Referenced Variables |
A reference is a variable name that is a duplicate of an existing variable. It provides a technique of creating more than one name to designate the same variable. To declare a reference variable, you use the reference operator expressed with the ampersand. The syntax of creating or declaring a reference is: DataType &RefernceName = VariableName; To declare a reference, type the variable’s name preceded by the same type as the variable it is referring to. Between the data type and the reference name, type the ampersand operator “&”. To specify what variable the reference is addressed to, use the assignment operator “=” followed by the name of the variable. The referred to variable must exist already. You cannot declare a reference as: int &mine; The compiler must know what variable you are referring to. Here is an example: #include <iostream> using namespace std; int main() { int number = 228; int &nbr = number; return 0; } The ampersand operator between the data type and the variable name can assume one of three positions as follows: int& nbr; int & nbr; int &nbr; As long as the & symbol is between a valid data type and a variable name, the compiler knows that the variable name (in this case Nbr) is a reference. Once a reference has been initialized, it holds the same value as the variable it is referring to. You can then display the value of the variable using either of both: #include <iostream> using namespace std; int main() { int number = 228; int & nbr = number; cout << "Number = " << number << "\n"; cout << "Its reference = " << nbr << "\n\n"; return 0; } If you change the value of the variable, the compiler updates the value of the reference so that both variables would hold the same value. In the same way, you can modify the value of the reference, which would update the value of the referred to variable. To access the reference, do not use the ampersand operator; just the name of the reference is sufficient to the compiler. This is illustrated in the following: #include <iostream> using namespace std; int main() { int number = 228; // Regular variable int& nbr = number; // Reference cout << "Number = " << number << "\n"; cout << "Its reference = " << nbr << "\n"; // Changing the value of the original variable number = 4250; cout << "\nNumber = " << number; cout << "\nIts reference = " << nbr << "\n"; // Modifying the value of the reference Nbr = 38570; cout << "\nNumber = " << number; cout << "\nIts reference = " << nbr << "\n\n"; return 0; } In the same way, you can use either a reference or the variable it is referring to, to request the variable’s value from the user. Here is an example: #include <iostream> using namespace std; int main() { double price; double& refPrice = price; cout << "What's the price? $"; cin >> price; cout << "Price = $" << price << "\n"; cout << "Same as: $" << refPrice << "\n\n"; cout << "What's the price? $"; cin >> refPrice; cout << "Price = $" << price << "\n"; cout << "Same as: $" << refPrice << "\n"; return 0; } If you change the value of the variable, the compiler updates the value of the reference so that both variables would hold the same value. In the same way, you can modify the value of the reference, which would update the value of the referred to variable. To access the reference, do not use the ampersand operator; just the name of the reference is sufficient to the compiler. This is illustrated in the following: #include <iostream> using namespace std; main() { int Number = 228; // Regular variable int& Nbr = Number; // Reference cout << "Number = " << Number << "\n"; cout << "Its reference = " << Nbr << "\n"; // Changing the value of the original variable Number = 4250; cout << "\nNumber = " << Number; cout << "\nIts reference = " << Nbr << "\n"; // Modifying the value of the reference Nbr = 38570; cout << "\nNumber = " << Number; cout << "\nIts reference = " << Nbr << "\n\n"; } In the way, you can use either a reference or the variable it is referring to, to request the variable’s value from the user. Here is an example: #include <iostream> using namespace std; main() { double Price; double& RefPrice = Price; cout << "What's the price? $"; cin >> Price; cout << "Price = $" << Price << "\n"; cout << "Same as: $" << RefPrice << "\n\n"; cout << "What's the price? $"; cin >> RefPrice; cout << "Price = $" << Price << "\n"; cout << "Same as: $" << RefPrice << "\n"; } |
Referenced Functions |
A function can be made to return a reference to a value. When defining such a function, make sure you type the reference operator to its left. After processing the function in its body, you must make sure you return a value that is a reference of the same type of the function. Here is an example: #ifdef __BORLANDC__ #pragma argsused #endif #include <iostream> using namespace std; int &GetNumberOfPages() { int pp = 842; int &pages = pp; return pages; } int main( int argc, char * argv[] ) { cout << "This book contains " << GetNumberOfPages() << " pages"; return 0; } If the function is not modifying any value it may have received, you can declare it as a constant: #ifdef __BORLANDC__ #pragma argsused #endif #include <iostream> using namespace std; const int &GetNumberOfPages() { int pp = 842; int &pages = pp; return pages; } int main( int argc, char * argv[] ) { cout << "This book contains " << GetNumberOfPages() << " pages"; return 0; } |
Static Variables and Functions |
Static Variables |
Consider the following program: |
#include <iostream> using namespace std; void Starter(int y) { double a = 112.50; double b = 175.25; a = a / y; b = b + 2; cout << "y = " << y << endl; cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "b / a = " << b / a << "\n\n"; } int main() { Starter(2); Starter(2); Starter(2); Starter(2); return 0; }
When executed, this program would produce: |
y = 2 a = 56.25 b = 177.25 b / a = 3.15111 y = 2 a = 56.25 b = 177.25 b / a = 3.15111 y = 2 a = 56.25 b = 177.25 b / a = 3.15111 y = 2 a = 56.25 b = 177.25 b / a = 3.15111
The Starter() function receives one argument passed when it is called. The called function also receives the same argument every time. Looking at the result, the argument passed to the function and the local variables declared inside of the called function keep the same value every time the function is called. That is, when the Starter() function is exited, the values remain the same. We know that, when a function is defined, any variable declared locally belongs to the function and its influence cannot expand beyond the body of the function. If you want a locally declared variable to keep its changed value when its host function is exited, declare such a variable as static. To declare a static variable, type the static keyword on the left of the variable’s data type. For example, if you plan to declare a Radius variable as static in an Area() function, you could write: |
double Area() { static double Radius; }
When you declare a variable as static, it is initialized with a 0 value. Otherwise, you can initialize it with a value of your choice when declaring it. To make the local variables of our Starter() function static, we can declare them as follows: |
void Starter(int y) { static double a = 112.50; static double b = 175.25; a = a / y; b = b + 2; cout << "y = " << y << endl; cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "b / a = " << b / a << "\n\n"; }
This time, when executing the program, it would produce: |
y = 2 a = 56.25 b = 177.25 b / a = 3.15111 y = 2 a = 28.125 b = 179.25 b / a = 6.37333 y = 2 a = 14.0625 b = 181.25 b / a = 12.8889 y = 2 a = 7.03125 b = 183.25 b / a = 26.0622
Notice that, this time, each local variable keeps its newly changed value when the function exits. Since a function’s argument can receive different values as the function is called different times, we can test our program by passing different values to its argument as follows: |
#include <iostream> using namespace std; void Starter(int y) { static double a = 112.50; static double b = 175.25; a = a / y; b = b + 2; cout << "y = " << y << endl; cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "b / a = " << b / a << "\n\n"; } int main() { Starter(2); Starter(5); Starter(14); Starter(25); return 0; }
The current version of the program would produce: |
y = 2 a = 56.25 b = 177.25 b / a = 3.15111 y = 5 a = 11.25 b = 179.25 b / a = 15.9333 y = 14 a = 0.803571 b = 181.25 b / a = 225.556 y = 25 a = 0.0321429 b = 183.25 b / a = 5701.11
Static Functions |
Like a variable, a function also can be declared and/or defined as static. Here is an example: #ifdef __BORLANDC__ #pragma argsused #endif #include <iostream> // #include "Exercise.h" using namespace std; static int GetNumberOfPages() { int pages = 842; return pages; } int main( int argc, char * argv[] ) { cout << "This book contains " << GetNumberOfPages() << " pages"; return 0; } |
|
||
Previous | Copyright © 1998-2015 FunctionX, Inc. | Next |
|