Home

Exploring Functions

 

Functions and their Arguments

 

Constant Arguments

When a function receives an argument, it performs one of two actions with regards to the value of the argument; it might modify the value itself or only use the argument to modify another argument or another of its own variables. If you know that the function is not supposed to alter the value of an argument, you should let the compiler know. This is a safeguard that serves at least two purposes. First, the compiler will make sure that the argument supplied stays intact; if the function tries to modify the argument, the compiler would throw an error, letting you know that an undesired operation took place. Second, this speeds up execution. 

To let the compiler know that the value of an argument must stay constant, use the const keyword before the data type of the argument. For example, if you declare a function like void Area(const string Side), the Area() function cannot modify the value of the Side argument. Consider a function that is supposed to calculate and return the perimeter of a rectangle if it receives the length and the width from another function, namely main(). Here is a program that would satisfy the operation (notice the Perimeter() function that takes two arguments):

#include <iostream>
using namespace std;

float Perimeter(float l, float w)
{
    double p;

    p = 2 * (l + w);
    return p;
}

int main()
{
    float length, width;

    cout << "Rectangle dimensions.\n";
    cout << "Enter the length: ";
    cin >> length;
    cout << "Enter the width: ";
    cin >> width;
    cout << "\nThe perimeter of the rectangle is: "
         << Perimeter(length, width) << "\n\n";
    
    return 0;
}

This would produce: 

Rectangle dimensions.
Enter the length: 35.55
Enter the width: 28.75

The perimeter of the rectangle is: 2044.12

As you can see, the Perimeter() function does not change the values of the length or the width. To reinforce the purpose of the assignment, you should make this clear to the compiler. To make the length and the width arguments constant, you would change the declaration of the Perimeter() function as follows:

float Perimeter(const float l, const float w);

You can make just one or more arguments constants, and there is no order on which arguments can be made constant.

Practical Learning Practical Learning: Using Constant Arguments

  1. Create a new project in a directory of folder called Constant Arguments
  2. If necessary, create a source file. Save the source file as Main.cpp
  3. To apply the "constantness" of arguments passed to functions, change the file as follows:
     
    #include <iostream>
    using namespace std;
    // 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, int)
    {
        return b * h * h * h / 12;
    }
    
    int main()
    {
        double base   = 7.74,
                  height = 14.38,
                  radius = 12.42;
    
        cout << "Rectangle\n"
             << "Moment of inertia with regard to the X axis: ";
        cout << "I = " << MomentOfInertia(base, height) << "mm\n\n";
    
        cout << "Semi-Circle\n"
             << "Moment of inertia with regard to the X axis: ";
        cout << "I = " << MomentOfInertia(radius) << "mm\n\n";
    
        cout << "Triangle\n"
             << "Moment of inertia with regard to the X axis: ";
        cout << "I = " << MomentOfInertia(base, height, 1) << "mm\n";
        
        return 0;
    }
  4. Test the program:
     
    Rectangle
    Moment of inertia with regard to the X axis: I = 7671.78mm
    
    Semi-Circle
    Moment of inertia with regard to the X axis: I = 9344.28mm
    
    Triangle
    Moment of inertia with regard to the X axis: I = 1917.95mm
  5. To use a mix of functions, change the program as follows:
     
    #include <iostream>
    using namespace std;
    // 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, int)
    {
        return b * h * h * h / 12;
    }
    
    int main()
    {
        double length, height, radius;
        double GetBase();
        double GetHeight();
        double GetRadius();
    
        cout << "Enter the dimensions of the rectangle\n";
        length = GetBase();
        height = GetHeight();
        cout << "Rectangle\n"
               << "Moment of inertia with regard to the X axis: ";
        cout << "I = " << MomentOfInertia(Length, Height) << "mm\n\n";
    
        cout << "Enter the radius of the semi-circle\n";
        radius = GetRadius();
        cout << "Semi-Circle\n"
               << "Moment of inertia with regard to the X axis: ";
        cout << "I = " << MomentOfInertia(Radius) << "mm\n\n";
    
        cout << "Enter the dimensions of the triangle\n";
        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;
    }
    
    double GetBase()
    {
        double b;
    
        cout << "Enter Base: ";
        cin >> b;
    
        return b;
    }
    
    double GetHeight()
    {
        double h;
    
        cout << "Enter Height: ";
        cin >> h;
        return h;
    }
    
    double GetRadius()
    {
        double r;
    
        cout << "Enter Radius: ";
        cin >> r;
        return r;
    }
  6. Test the program. Here is an example:
     
    Enter the dimensions of the rectangle
    Enter Base: 18.25
    Enter Height: 14.15
    Rectangle
    Moment of inertia with regard to the X axis: I = 17235mm
    
    Enter the radius of the semi-circle
    Enter Radius: 15.55
    Semi-Circle
    Moment of inertia with regard to the X axis: I = 22960.5mm
    
    Enter the dimensions of the triangle
    Enter Base: 16.35
    Enter Height: 12.75
    
    Triangle
    Moment of inertia with regard to the X axis: I = 2824.02mm
  7. After examining the program, return to your programming environment

An Argument as a Constant Reference

If you pass an argument as reference, the compiler would access the argument from its location. The called function can modify the value of the argument. The advantage is that the code execution is faster because the argument gives access to its address. The disadvantage could be that if the calling function modifies the value of the argument, when the function exits, the value of the argument would have (permanently) changed and the original value would be lost (actually, this can be an advantage as we have learned in the passed). If you do not want the value of the passed argument to be modified, you should pass the argument as a constant reference. When doing this, the compiler would access the argument at its location (or address) but it would make sure that the value of the argument stays intact.

To pass an argument as a constant reference, when declaring the function and when implementing it, type the const keyword, followed by the argument data type, followed by the ampersand operator, followed by a name for the argument. When declaring the function, the name of the argument is optional. Here is a function that receives an argument as a constant reference:

double CalculateNetPrice(const double& tax)
{
    double original;
    const double discount = 25;

    Original = GetOriginalPrice();
    double discountValue = original * discount / 100;
    double taxValue = tax / 100;
    double netPrice = original - discountValue + taxValue;

    return NetPrice;
}

You can mix arguments passed by value, those passed as reference, those passed by constant, and those passed by constant references. You will decide, based on your intentions, to apply whatever technique suits your scenario.

The following program illustrates the use of various techniques of passing arguments: 

#include <iostream>
using namespace std;

// Passing an argument by reference
void GetOriginalPrice(double& originalPrice)
{
    cout << "Enter the original price of the item: $";
    cin >> originalPrice;
}

// Passing an argument as a constant reference
// Passing arguments by value
double CalculateNetPrice(const double& original, double tax, double discount)
{
    discount = original * discount / 100;
    tax = tax / 100;
    double netPrice = original - discount + tax;

    return netPrice;
}

int main()
{
    double taxRate = 5.50; // = 5.50%
    const double tiscount = 25;
    double price;
    double original;
    void Receipt(const double& orig, const double& taxation,
    const double& dis, const double& final);

    GetOriginalPrice(original);
    price = CalculateNetPrice(original, taxRate, discount);
    Receipt(original, taxRate, discount, price);

    cout << "\n\n";   
    return 0;
}

void Receipt(const double& original, const double& tax,
                  const double& discount, const double& finalPrice)
{
    cout << "\nReceipt";
    cout << "\nOriginal Price: $" << original;
    cout << "\nTax Rate: " << tax << "%";
    cout << "\nDiscount Rate: " << discount << "%";
    cout << "\nFinal Price: $" << finalPrice;
}

Practical Learning Practical Learning: Passing Arguments by Constant References

  1. To illustrate the passing of arguments by reference and by constant references, change the program as follows:
     
    #include <iostream>
    using namespace std;
    
    // 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;
    }
    
    int main()
    {
        double length, height, radius;
        void GetBaseAndHeight(double&, double&);
        void GetRadius(double&);
    
        cout << "Enter the dimensions of the rectangle\n";
        GetBaseAndHeight(length, height);
        cout << "Rectangle\n"
                << "Moment of inertia with regard to the X axis: ";
        cout << "I = " << MomentOfInertia(length, height) << "mm\n\n";
    
        cout << "Enter the radius of the semi-circle\n";
        GetRadius(radius);
        cout << "Semi-Circle\n"
                << "Moment of inertia with regard to the X axis: ";
        cout << "I = " << MomentOfInertia(radius) << "mm\n\n";
    
        cout << "Enter the dimensions of the triangle\n";
        GetBaseAndHeight(length, height);
    
        cout << "\nTriangle\n"
                << "Moment of inertia with regard to the X axis: ";
        cout << "I = " << MomentOfInertia(length, height, 1) << "mm\n";
    
        cout << "\n\n";
        
        return 0;
    }
    
    // Passing arguments by reference
    void GetBaseAndHeight(double& B, double& H)
    {
        cout << "Enter Base:   ";
        cin >> B;
        cout << "Enter Height: ";
        cin >> H;
    }
    
    void GetRadius(double& R)
    {
        cout << "Enter Radius: ";
        cin >> R;
    }
  2. Test the program. Here is an example:
  3. Enter the dimensions of the rectangle
    Enter Base:   18.85
    Enter Height: 15.55
    Rectangle
    Moment of inertia with regard to the X axis: I = 23625.5mm
    
    Enter the radius of the semi-circle
    Enter Radius: 14.25
    Semi-Circle
    Moment of inertia with regard to the X axis: I = 16192.7mm
    
    Enter the dimensions of the triangle
    Enter Base:   8.95
    Enter Height: 11.25
    
    Triangle
    Moment of inertia with regard to the X axis: I = 1061.94mm
  4. After testing the program, return to your programming environment
  5. To further mix the passing of arguments, change the program as follows:
     
    #include <iostream>
    using namespace std;
    
    // Rectangle
    // This function receives one argument by reference and two arguments
    // by constant references
    void MomentOfInertia(double& moment,
                         const double& b, const double& h)
    {
        moment = b * h * h * h / 3;
    }
    
    // Semi-Circle
    // This function receives one argument by reference and one by
    // constant reference
    void MomentOfInertia(double& moment, const double& R)
    {
        const double PI = 3.14159;
    
        moment = R * R * R * R * PI/ 8;
    }
    
    // Triangle
    // This function receives one argument by reference, two arguments by
    // constant references and one argument by value
    void MomentOfInertia(double& moment,
                           const double& b, const double& h, const int&)
    {
        moment = b * h * h * h / 12;
    }
    
    int main()
    {
        double length, height, radius, mRectangle, mSemiCircle, mTriangle;
        void GetBaseAndHeight(double&, double&);
        void GetRadius(double&);
    
        cout << "Enter the dimensions of the rectangle\n";
        GetBaseAndHeight(length, height);
        MomentOfInertia(mRectangle, length, height);
        cout << "Rectangle\n"
             << "Moment of inertia with regard to the X axis: ";
        cout << "I = " << mRectangle << "mm\n\n";
        cout << "Enter the radius of the semi-circle\n";
    
        GetRadius(radius);
        MomentOfInertia(mSemiCircle, radius);
        cout << "Semi-Circle\n"
             << "Moment of inertia with regard to the X axis: ";
        cout << "I = " << mSemiCircle << "mm\n\n";
        cout << "Enter the dimensions of the triangle\n";
    
        GetBaseAndHeight(length, height);
        MomentOfInertia(mRectangle, length, height, 1);
        cout << "\nTriangle\n"
             << "Moment of inertia with regard to the X axis: ";
        cout << "I = " << mRectangle << "mm\n";
    
        cout << "\n\n";
        
        return 0;
    }
    
    // Passing arguments by reference
    void GetBaseAndHeight(double& b, double& h)
    {
        cout << "Enter Base:   ";
        cin >> b;
        cout << "Enter Height: ";
        cin >> h;
    }
    
    void GetRadius(double& R)
    {
        cout << "Enter Radius: ";
        cin >> R;
    }
  6. Test the program. Here is an example:
     
    Enter the dimensions of the rectangle
    Enter Base:   12.85
    Enter Height: 8.85
    Rectangle
    Moment of inertia with regard to the X axis: I = 2969.01mm
    
    Enter the radius of the semi-circle
    Enter Radius: 5.55
    Semi-Circle
    Moment of inertia with regard to the X axis: I = 372.59mm
    
    Enter the dimensions of the triangle
    Enter Base:   10.75
    Enter Height: 6.75
    
    Triangle
    Moment of inertia with regard to the X axis: I = 275.511mm
  7. Return to your programming environment

 

 

Functions and Namespaces

 

Functions Local Definition

Like a variable, a function can be part of a namespace. To declare a function in a namespace, provide its return type, followed by a name, followed by the argument(s), if any, inside of parentheses. Here is an example:

namespace InterestAndDiscount
{
    double Principal;
    double Rate;
    int    Time; 
    double CalculateDiscount();
    double CalculateInterest();
    double CalculateMaturity();
}

A member function of a namespace can be accessed using the scope access operator.

There are two main ways you can implement a member function. In the body of the namespace, which is a local implementation, delimit the body of the function with an opening curly bracket { and a closing curly bracket }. A function that is a member of a namespace has complete access to the member variables of the same namespace. Therefore, you do not have to pass the member variables as arguments to the member functions. Here is an example: 

#include <iostream>
using namespace std;

namespace InterestAndDiscount
{
    double Principal;
    double Rate;
    int    Time;
    double GetInterestRate()
    {
 	return Rate / 100;
    }
    double CalculateInterest()
    {
	return Principal * GetInterestRate() * Time;
    }
    double CalculateMaturity()
    {
	return Principal + CalculateInterest();
    }
}

int main()
{
    using namespace InterestAndDiscount;
    Principal = 12500; // $
    Rate = 12.25; // %
    Time = 4; // Years

    cout << "Interest Calculation";
    cout << "\nPrincipal: $" << Principal
           << "\nRate:       " << Rate << "%"
           << "\nTime:       " << Time << " years"
           << "\nInterest:  $" << CalculateInterest()
           << "\nMaturity:  $" << CalculateMaturity() << "\n\n";

    return 0;
}

This would produce: 

Interest Calculation
Principal: $12500
Rate:       12.25%
Time:       4 years
Interest:  $6125
Maturity:  $18625

If a nested namespace has its own functions, you can also implement them in the body of the nested namespace. Here is an example: 

namespace InterestAndDiscount
{
    double Principal;
    double Rate;
    int    Time;
	double GetInterestRate()
	{
		return Rate / 100;
	}
	double CalculateInterest()
	{
		return Principal * GetInterestRate() * Time;
	}
	double CalculateMaturity()
	{
		return Principal + CalculateInterest();
	}
	namespace Discounter
	{
		double Maturity;
		double DiscountRate;
		double TermOfDiscount;
		double Discount()
		{
			return Maturity * DiscountRate * TermOfDiscount;
		}
	}
}

After locally implementing the member functions of a nested namespace, you can access its members and display their value in the main() function as done above.

 

Functions Global Definitions

To implement a member function outside the body of a namespace, provide the return type, followed by the name of the namespace, followed by the scope access operator ::. Here is an example:

namespace InterestAndDiscount
{
    double Principal;
    double Rate;
    int    Time;
    double GetInterestRate();
    double CalculateInterest();
    double CalculateMaturity();
}

InterestAndDiscount::GetInterestRate()
{
	return Rate / 100;
}
InterestAndDiscount::CalculateInterest()
{
	return Principal * GetInterestRate() * Time;
}

InterestAndDiscount::CalculateMaturity()
{
	return Principal + CalculateInterest();
}

To implement the member functions of a nested namespace outside of the parent namespace, you must qualify each member function to specify the function (or the variable) you are calling. Here is an example: 

namespace InterestAndDiscount
{
    double Principal;
    double Rate;
    int    Time;
    double GetInterestRate();
    double CalculateInterest();
    double CalculateMaturity()
	
    namespace Discounter
    {
	double Maturity;
	double DiscountRate;
	double TermOfDiscount;
	double Discount();
    }
}

. . .

InterestAndDiscount::Discounter::Discount()
{
	return Maturity * DiscountRate * TermOfDiscount;
}

Namespaces and External Functions

The member variables of a namespace are variables like any of those we have used so far. They can request their values from an outside function. Here is an example: 

#include <iostream>
using namespace std;

namespace InterestAndDiscount
{
	. . .
}

	. . .

int main()
{
	using namespace InterestAndDiscount;
		
	double GetThePrincipal();

	cout << "Loan Processing\n";
	cout << "Enter the following values\n";
	Principal = GetThePrincipal();
	cout << "Rate (between 0 and 100): ";
	cin >> Rate;
	cout << "Time (number of years): ";
	cin >> Time;

	cout << "\nInterest on a loan";
	cout << "\nPrincipal: $" << Principal;
	cout << "\nRate: " << Rate << "%";
	cout << "\nTime: " << Time << " years";
	cout << "\nInterest: $" << CalcInterest();
	cout << "\nMaturity Value: $" << CalcMaturityValue();
	
	return 0;
}

double GetThePrincipal()
{
	double P;

	cout << "Principal: $";
	cin >> P;
	return P;
}

The member variable of a namespace can also be passed as argument to a function. When passing the argument, if the using namespace routine has been entered, you can pass the argument like any other. Otherwise, you should qualify the namespace member with the :: operator. In the following example, one member of a namespace is passed by its name only because of the previous using namespace. The other members are passed by being qualified, which is for demonstration purposes only:

#include <iostream>
using namespace std;

namespace InterestAndDiscount
{
    . . .
}

    . . .

int main()
{
    using namespace InterestAndDiscount;

    void GetThePrincipal(double& p);
    void RateAndTime(double &r, double &t);

    cout << "Loan Processing";
    cout << "\nEnter the following values\n";

    GetThePrincipal(Principal);
    RateAndTime(InterestAndDiscount::Rate, InterestAndDiscount::Time);

    cout << setiosflags(ios::fixed) << setprecision(2);
    cout << "\nInterest on a loan";
    cout << "\nPrincipal: $" << Principal;
    cout << "\nRate: " << Rate << "%";
    cout << setiosflags(ios::fixed) << setprecision(0);
    cout << "\nTime: " << Time << " years";
    cout << setiosflags(ios::fixed) << setprecision(2);
    cout << "\nInterest: $" << CalcInterest();
    cout << "\nMaturity Value: $" << CalcMaturityValue();
    
    return 0;
}

void GetThePrincipal(double& P)
{
    cout << "Principal: $";
    cin >> P;

    while( P < 0 )
    {
        cout << "Enter a positive number: $";
        cin >> P;
    }
}

void RateAndTime(double &rate, double &time)
{
    do {
        cout << "Rate (between 0 and 100): ";
        cin >> rate;
    } while(rate < 0 || rate > 100);

    do {
        cout << "Time (Nbr of Years): ";
        cin >> time;
    } while(time <= 0 || time >= 30);
}
 

C++ Built-in Functions

 

Introduction

Although as a smart programmer you can create any function to perform a desired job, the C++ language provides a series of functions already made so you can just add them to your program without caring how they work, all you need to know is what these functions do. The functions that are part of the C++ language are highly valuable, were tested sufficiently, and are completely reliable. The C++ built-in functions are made for various assignments ranging from algebra, geometry, trigonometry, and finance, etc. Besides the functions that are part of the C++ Standard, each compiler ships with its own set of functions that may not be available on other compilers. Borland C++ Builder provides an extremely rich library of functions.

 

Asserting a Value or an Expression

Most of the values you use in your program will need to fit in an interval of your choice. For example, when requesting the age of a person, you would need such a value to be positive. After all, you do not expect a person to be 26 years old. C++ provides a function that can be used to check that a value or expression responds to a criteria of your choice. This function is called assert() and is defined in the cassert library of the std namespace. Its syntax is:

void assert(int Expression);

The assert() function considers an expression as its argument and tests it. This function is used in the same context as the conditional statements we will study in the next lesson of this book. If the Expression is true, assert() acknowledges that and lets the compiler continue with the next operation. If the Expression is false, assert() displays a (nasty) message. Although we have not yet learned conditional statements, the following is an example that requests the age of a student and checks that the supplied age is valid only if the student is older than 8:

#include <iostream>
#include <cassert>
using namespace std;

int main()
{
	float StudentAge;

	cout << "Type Student's Age: ";
	cin >> StudentAge;
	assert(StudentAge > 8);

	cout << "Student Age: " << StudentAge << "\n\n";

	return 0;
}

Mathematic Functions

The C++ language also provides a series of functions to perform various mathematically related operations. The functions are defined in various libraries and this can depend on the compiler you are using.

The functions defined in the cmath library are:

acos cos fmod modf tan
asin cosh frexp pow tanh
atan exp ldexp sin  
atan2 fabs log sinh  
ceil floor log10 sqrt  

Additional functions are defined in the cstdlib library and they are:

abs labs srand
div ldiv rand

 

 

Previous Copyright 1998-2006 FunctionX, Inc. Next