This post is also available in: en, en and en

The mechanism of C++: from source code to a running program

Introduction and objectives

In [1]:
!cat Inequalities.hpp
// Inequalities.hpp
//
// Header file containing declarations of functions
//
// (C) Datasim Education BV 2006
//

// Preprocessor directives; ensures that we do not 
// include a file twice (gives compiler error)
#ifndef Inequalities_HPP
#define Inequalities_HPP

/////////// Useful functions //////////////////

// Max and Min of two numbers
double Max(double x, double y);
double Min(double x, double y);

// Max and Min of three numbers
double Max(double x, double y, double z);
double Min(double x, double y, double z);

////////////////////////////////////////////////

#endif
In [2]:
!cat Inequalities.cpp
// Inequalities.cpp
//
// Code file containing bodies of functions
//
// Last Modification Dates:
//
//	2006-2-17 DD kick-off code
//
// (C) Datasim Education BV 2006
//

#include "Inequalities.hpp"

/////////// Useful functions //////////////////

// Max and Min of two numbers
double Max(double x, double y)
{
	if (x > y)
		return x;

	return y;
}

double Min(double x, double y)
{
	if (x < y)
		return x;

	return y;
}

// Max and Min of three numbers
double Max(double x, double y, double z)
{
	return Max(Max(x,y), z);
}

double Min(double x, double y, double z)
{
	return Min(Min(x,y), z);
}
In [3]:
!cat TestInequalities.cpp
// TestInequalities.cpp
//
// Main program (Console-based) to test Max and 
// Min functions.
//
// (C) Datasim Education BV 2006
//

#include <iostream>		// Console input and output

#include "Inequalities.hpp"

int main()
{
	// Prompt the user for input. Console output (cout)
	// and input (cin)
	double d1, d2;
	std::cout << "Give the first number: ";
	std::cin >> d1;
	std::cout << "Give the second number: ";
	std::cin >> d2;

	char c;	// Character type
	std::cout << "Which function a) Max() or b) Min()? ";
	std::cin >> c;
	if (c == 'a')
	{
		std::cout << "Max value is: " << Max(d1, d2) << std::endl;
	}
	else
	{
		std::cout << "Min value is: " << Min(d1, d2) << std::endl;
	}

	double dA = 1.0; double dB = 2.0; double dC = 3.0;
	std::cout << "\n\nMax and min of three numbers: " << std::endl;
	std::cout << "Max value is: " << Max(dA, dB, dC) << std::endl;
	std::cout << "Min value is: " << Min(dA, dB, dC) << std::endl;

	return 0;
}
In [12]:
#include "Inequalities.cpp"
#include <iostream>
In [16]:
{
    double d1, d2;
    char c;	// Character type

    std::cout << "Give the first number: ";
    std::cin >> d1;

    std::cout << "Give the second number: ";
    std::cin >> d2;

    std::cout << "Which function a) Max() or b) Min()? ";
    std::cin >> c;
    
    if (c == 'a')
    {
        std::cout << "Max value is: " << Max(d1, d2) << std::endl;
    }
    else
    {
        std::cout << "Min value is: " << Min(d1, d2) << std::endl;
    }
}
Give the first number: 10
Give the second number: 20
Which function a) Max() or b) Min()? a
Max value is: 20

Creating classes and using their objects

We now discuss how to set up a program that uses C++ classes. This is not much more difficult than in the previous section and in this case we use three files:

  • Header file describing the class members (data and functions).
  • Code file containing the bodies of member functions.
  • File containing the test program.
In [19]:
!cat Person.hpp
// Person.hpp
//
// 'Hello World' class. Function declarations.
//
// (C) Datasim Education BV 2005-2006
//

#ifndef Person_HPP
#define Person_HPP

#include "DatasimDate.hpp"	// My dates and other useful stuff
#include <string>			// Standard string class in C++

class Person
{
public: // Everything public, for convenience only

		// Data
		std::string nam;					// Name of person
		DatasimDate dob;			// Date of birth

		DatasimDate createdD;		// Internal, when object was created

public:
		Person (const std::string& name, const DatasimDate& DateofBirth);


		void print() const;
		
		int age() const;
		
};

#endif
In [20]:
!cat Person.cpp
// Person.cpp
//
// 'Hello World' class 
//
// Last Modification Dates
//
// 2006-2-17 DD Kick-off
//
// (C) Datasim Education BV 2005-2006
//


#include "Person.hpp"

Person::Person (const std::string& name, const DatasimDate& DateofBirth)
{
			nam = name;
			dob = DateofBirth;
			createdD = DatasimDate();	// default, today REALLY!

}

void Person::print() const
{ // Who am I?
			
			std::cout << "\n** Person Data **\n";
		
			std::cout << "Name: " << nam << ", Date of birth: " << dob 
						<< ", Age: " << age() << std::endl;

}

int Person::age() const
{
		return int( double(DatasimDate() - dob) / 365.0);
}

In [21]:
!cat TestPerson.cpp
// TestPerson.cpp
//
// 'Hello World' Testing the first C++ class
//
// (C) Datasim Education BV 2005-2006
//


#include "DatasimDate.hpp"	// Dates and other useful stuff
#include "Person.hpp"		// Interface functions for Person
#include <string>			// Standard string class in C++

int main()
{

	DatasimDate myBirthday(29, 8, 1952);
	std::string myName ("Daniel J. Duffy");
	Person dd(myName, myBirthday);
	dd.print();

	DatasimDate bBirthday(06, 8, 1994);
	std::string bName ("Brendan Duffy");
	Person bd(bName, bBirthday);
	bd.print();
	
	return 0;
}
In [1]:
#include <string>
#include "DatasimDate.cpp"
#include "Person.cpp"
In [19]:
{
    DatasimDate myBirthday(29, 8, 1952);
    std::string myName ("Daniel J. Duffy");
    Person dd(myName, myBirthday);
    dd.print();
}
** Person Data **
Name: Daniel J. Duffy, Date of birth: 29/8/1952, Age: 67
In [7]:
{
    DatasimDate bBirthday(06, 8, 1994);
    std::string bName ("Brendan Duffy");
    Person bd(bName, bBirthday);
    bd.print();
}
** Person Data **
Name: Brendan Duffy, Date of birth: 6/8/1994, Age: 25

Template classes and template functions

We now turn our attention to the last relevant topic, namely facility in C++ to support generic classes and functions. Instead of having work with specific and hard-wired entities we can create types. Of course, templates will be discussed later in this book but the focus here is on showing what needs to be done to compile, link and run programs that use template classes and functions.

Templates are trickier because we must include the file (whatever its name may be) that contains the bodies of the functions that we are calling. In order to motivate we wish to make the functions in section 2.3 more generic in the sense that we would like to use them with other data types such as C++ built-in types and even user-defined types. To this end, we copy the original header and code files and we add some new syntax to signal that the functions now depend on a generic type. The new header file is:

In [29]:
!cat GenericInequalities.hpp
// GenericInequalities.hpp
//
// Header file containing declarations of functions
//
// This is the template/generic version.
//
// (C) Datasim Education BV 2006
//

// Preprocessor directives; ensures that we do not 
// include a file twice (gives compiler error)
#ifndef GenericInequalities_HPP
#define GenericInequalities_HPP

/////////// Useful functions //////////////////

// Max and Min of two numbers
template <class Numeric>
Numeric Max(const Numeric& x, const Numeric& y);
template <class Numeric>
Numeric Min(const Numeric& x, const Numeric& y);

// Max and Min of three numbers
template <class Numeric>
Numeric Max(const Numeric& x, const Numeric& y, const Numeric& z);
template <class Numeric>
Numeric Min(const Numeric& x, const Numeric& y, const Numeric& z);

#include "GenericInequalities.cpp"

#endif
In [30]:
!cat GenericInequalities.cpp
// Generic& valueInequalities.cpp
//
// Code file containing bodies of functions
//
// Last Modific& valueation Dates:
//
//	2006-2-17 DD kic& valuek-off code
//	2006-2-17 DD Copied from non-generic& value structure
//
// (C) Datasim Education BV 2006
//

#ifndef GenericInequalities_CPP
#define GenericInequalities_CPP

#include "GenericInequalities.hpp"

/////////// Useful functions //////////////////

// Max and Min of two numbers
template <class Numeric>
Numeric Max(const Numeric& x, const Numeric& y)
{
	if (x > y)
		return x;

	return y;
}

template <class Numeric>
Numeric Min(const Numeric& x, const Numeric& y)
{
	if (x < y)
		return x;

	return y;
}

// Max and Min of three numbers
template <class Numeric>
Numeric Max(const Numeric& x, const Numeric& y, const Numeric& z)
{
	return Max<Numeric>(Max<Numeric>(x,y), z);
}

template <class Numeric>
Numeric Min(const Numeric& x, const Numeric& y, const Numeric& z)
{
	return Min<Numeric>(Min<Numeric>(x,y), z);
}

#endif
In [31]:
!cat TestGenericInequalities.cpp
// TestGenericInequalities.cpp
//
// Main program (Console-based) to test Max and 
// Min functions.
//
// (C) Datasim Education BV 2006
//

#include <iostream>		// Console input and output

#include "GenericInequalities.hpp" // Needed because it is templated
int main()
{
	// Prompt the user for input. Console output (cout)
	// and input (cin)
	int d1, d2;
	std::cout << "Give the first number: ";
	std::cin >> d1;
	std::cout << "Give the second number: ";
	std::cin >> d2;

	char c;	// Character type
	std::cout << "Which function a) Max() or b) Min()? ";
	std::cin >> c;
	if (c == 'a')
	{
		std::cout << "Max value is: " << Max<int>(d1, d2) << std::endl;
	}
	else
	{
		std::cout << "Min value is: " << Min<int>(d1, d2) << std::endl;
	}

	long dA = 12334; long dB = 2; long dC = -3;
	std::cout << "\n\nMax and min of three numbers: " << std::endl;
	std::cout << "Max value is: " << Max<long>(dA, dB, dC) << std::endl;
	std::cout << "Min value is: " << Min<long>(dA, dB, dC) << std::endl;

	return 0;
}
In [8]:
#include "GenericInequalities.cpp"
In [18]:
{
    int d1, d2;
    std::cout << "Give the first number: ";
    std::cin >> d1;

    std::cout << "Give the second number: ";
    std::cin >> d2;

    char c;	// Character type
    std::cout << "Which function a) Max() or b) Min()? ";

    long dA = 12334, dB = 2, dC = -3;

    std::cout << "\n\nMax and min of three numbers: " << std::endl;
    std::cout << "Max value is: " << Max<long>(dA, dB, dC) << std::endl;
    std::cout << "Min value is: " << Min<long>(dA, dB, dC) << std::endl;
}
Give the first number: 10
Give the second number: 20
Which function a) Max() or b) Min()? 

Max and min of three numbers: 
Max value is: 12334
Min value is: -3

Kinds of errors

One of the most annoying aspects of programming is getting a bunch of error messages on your console and wondering to yourself:

  • Where did these messages come from?
  • What do these messages mean?
  • How do I resolve these messages?
  • What am I doing to do, it's driving me crazy?! What we need to do is to remain calm and collected and think about what is realling happening. Errors arise in different places and for different reasons. We attempt to categorise these errors and give some typical examples in the hope that you will be able to resolve them quickly and efficiently. It does not do any harm to actually read and try to understand compiler errors, no matter how cryptic they might be.

Compiler errors

These are errors that arise when we compile a source file in an attempt to transform the text in the file to binary form. The two main sources of error are:

E1: Syntax errors.

E2: Compiler unable to find a class.

Linker errors

In the linkage phase all the functions bodies are brought together as it were to produce an executable file. The modules comprising a program need not all be compiled at one time. Normally the source text is kept in separate files and precompiled routines may be loaded from libraries. So basically, in the linkage phase we need to associate all the identifiers originating from separately compiled translation units.

Linkage errors occur because the bodies of functions or the initialization of data cannot be found. The root cause of these erros is usually:

E1: A typing error; for example, mismatch between the signature of a function as declared in a header file and its definition in the code file.

E2: You forgot to add the relevant source file to your project.

Run-time errors

These are the errors that occur when you run the executable file. Basically, when a run-time error occurs the program halts and you are left with a meaningless dialog box on your screen. Run-time errors have many causes, some of which are:

E1: Memory management errors: the C++ program writes into a piece of memory that has not been reserved.

E2: Overflow/underflow errors: very large or very small numbers arise in the program and cause the program to crash.

E3: Logic errors: the user has entered a value that is not allowed.

In [2]:
#include <iostream>
#include <sstream>
#include <string>
In [3]:
// Hard-coded example for starters
{
    double myDouble = 1.0;
    std::stringstream s;
    s << myDouble;
    std::string result = s.str();
    std::cout << "String value is: " << result << std::endl;
}
String value is: 1
In [4]:
template <typename T> std::string getString(const T& value)
{
    std::stringstream s;
    s << value;
    return s.str();
}
In [2]:
!cat TestConversions.cpp
// TestConversions.cpp
//
// Simple stuff for converting built-in
// types to strings.
//
// (C) Datasim Education BV 2006
//

#include <sstream>
#include <string>
#include <iostream>

template <typename T>
	std::string getString(const T& value)
{
		std::stringstream s;
		s << value;
		
		return s.str();
}

int main()
{

	// Hard-coded example for starters
	double myDouble = 1.0;
	std::stringstream s;
	s << myDouble;
	std::string result = s.str();
	std::cout << "String value is: " << result << std::endl;

	int i = 10;
	long j = 1234567890;
	float f = 3.14f;
	double d = 2.712222222223;

	std::string myString = getString<int>(i);
	std::cout << myString << std::endl;

	myString = getString<long>(j);
	std::cout << myString << std::endl;

	myString = getString<float>(f);
	std::cout << myString << std::endl;

	myString = getString<double>(d);
	std::cout << myString << std::endl;

	return 0;
}
In [8]:
{
    int i = 10;
    long j = 1234567890;
    float f = 3.14f;
    double d = 2.7122222223;
    
    std::string myString = getString<int>(i);
    std::cout << myString << std::endl;
    
    myString = getString<double>(j);
    std::cout << myString << std::endl;
    
    myString = getString<float>(f);
    std::cout << myString << std::endl;
    
    myString = getString<double>(d);
    std::cout << myString << std::endl;
}
10
1.23457e+09
3.14
2.71222
In [9]:
#include <string>
#include <cstddef>
In [3]:
std::string getString(long j)
{
    char str[200];
    sprintf(str, "%ld", j);
    std::string result(str);
    
    return result;
}
/*
std::string getString(int j)
{
    char str[200];
    sprintf(str, "%d", j);
    std::string result(str);
    
    return result;
}

std::string getString(std::size_t j)
{
    char str[200];
    sprintf(str, "%d", j);
    std::string result(str);
    
    return result;
}
*/
input_line_9:1:13: error: redefinition of 'getString'
std::string getString(long j)
            ^
input_line_8:1:13: note: previous definition is here
std::string getString(long j)
            ^
Interpreter Error: 

Published

Last Updated

Category

c++

Tags

Contact