This post is also available in: en, en and en
The mechanism of C++: from source code to a running program¶
Introduction and objectives¶
!cat Inequalities.hpp
!cat Inequalities.cpp
!cat TestInequalities.cpp
#include "Inequalities.cpp"
#include <iostream>
{
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;
}
}
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.
!cat Person.hpp
!cat Person.cpp
!cat TestPerson.cpp
#include <string>
#include "DatasimDate.cpp"
#include "Person.cpp"
{
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();
}
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:
!cat GenericInequalities.hpp
!cat GenericInequalities.cpp
!cat TestGenericInequalities.cpp
#include "GenericInequalities.cpp"
{
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;
}
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.
#include <iostream>
#include <sstream>
#include <string>
// 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;
}
template <typename T> std::string getString(const T& value)
{
std::stringstream s;
s << value;
return s.str();
}
!cat TestConversions.cpp
{
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;
}
#include <string>
#include <cstddef>
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;
}
*/