Introduction To C++: INAF - Osservatorio Astronomico Di Trieste
Introduction To C++: INAF - Osservatorio Astronomico Di Trieste
Introduction To C++: INAF - Osservatorio Astronomico Di Trieste
Day 1
Marco Frailis
INAF – Osservatorio Astronomico di Trieste
An object packages both data and procedures that operate on the data
Such procedures are called member functions or methods or
operations
The implementation of an object is specified in its class, which defines
the internal data (or attributes) of the object and the operations that
the object can perform
New classes can be defined as subclasses of a parent class,
inheriting its attributes and operations
An abstract class is one whose main purpose is to define a common
interface for its subclasses
When inheriting from an abstract class, we speak about polimorphism,
since the same interface is associated to different implementations
through its subclasses.
LSST
Core processing developed in C++
ALMA
ACS software: C++ implementation for the control system
MAGIC telescopes
MARS, the analysis and reconstruction software is based on ROOT and written in C++
Euclid
C++ and Python selected for developing all the processing levels
FITS standard
cfitsio (C)
CCfits (C++)
http://en.cppreference.com/w/
https://isocpp.org/faq
http://www.stroustrup.com/C++11FAQ.html
On-line tutorials
http://www.tutorialspoint.com/cplusplus/index.htm
http://www.cplusplus.com/doc/tutorial/
http://www.learncpp.com/
http://www.cprogramming.com/tutorial/c++-tutorial.html
Code::Blocks (
http://www.codeblocks.org/)
A lightweight IDE (it is provided in
the virtual machine created for
this course)
Eclipse CDT
(https://eclipse.org/cdt/)
Emacs (http://www.gnu.org/software/emacs/)
Others:
QT Creator, Xcode (Mac OS X), Visual Studio (Windows)
Marco Frailis Introduction to C++ 26 Feb 2015 11/45
C++ program: main function example
#include <cmath> Including standard library
#include <iostream>
functions and classes
using namespace std;
// Norm
double r = sqrt(x*x + y*y + z*z);
cout << "Longitude = " << phi*RAD2DEG << " deg, Colatitude = "
<< theta*RAD2DEG << " deg, Radius = " << r << endl; Printing output
return 0;
}
C++ source code should be given one of the valid C++ file extensions:
.cpp, .cc, .cxx or .C, while the .c extension is reserved to C programs
Saving the previous source code in file “coord.cpp”, in order to compile
it and create an executable, we can use the GNU g++ compiler:
Many C++ fundamental facilities, such as I/O, are not part of the core
language
They are part of the standard library. These facilities are requested
using the #include directive
Example: requesting the I/O standard library facilities and standard
strings
#include <iostream>
#include <string>
A definition may also provide an initial value for the object (initialization)
C++ supports four forms of variable initialization: copy-initialization,
direct-initialization, list-copy-initialization, list-direct-initialization
int month = 9, year = 2012, day; // copy-initialization OK for built-in
double salary(1250.23); // direct-initialization types
C++11
std::complex<float> c = {-1.0, 0.0}; // list-copy-initialization Recommended
long int count{35600}; // list-direct-initialization for class types
// Character types
char single_letter = 'D';
// Integer types
char tiny_value = 127;
short small_value = 32767;
int value = 2147483647;
long large_value = 2147483647;
long long huge_value = -9.22E18LL;
Relational operators:
a < b a <= b
a > b a >= b
a == b a != b
Logical operators
|| or (a < 0) || (a >= 5)
Bitwise operators:
Operator Meaning Example
<< left shift a << 3
>> right shift a >> 2
& bitwise and a & mask
| bitwise or a | mask
^ bitwise xor a ^ mask
~ bitwise not ~mask
// assignment
deltaT = 0.3;
index = step * deltaT ; // here an implicit truncation is performed
int i = 0, j;
j = ++i; // j = 1 , i = 1;
j = i++; // j = 1 , i = 2;
int x = 37, y = 6;
float result = (float) x / y; // or float(x) / y
result = static_cast<float>(x) / y;
int main()
{
std::string s1; // s1 is an empty string
std::string s2(s1); // s2 is initialized as a copy of s1
std::string s3("swing") // s3 is a copy of the string literal
std::string s4(5,'-'); // s4 = "-----"
}
int main()
{
string s1;
string s2 = "Hell0";
string s3 = s2 + " World"; // string + literal concatenation
The standard library defines a family of types that support I/O to and from
devices such as files and console windows. Additional types allow strings to
act like I/O streams
The I/O types are defined in three separate headers:
<iostream> defines the types used to read from and write to a console
window
<fstream> defines the types used to read from and write to named files
<sstream> defines the types used to read from a and write to in-
memory strings
The iostream header includes the definition of three I/O objects:
The istream object named cin, also referred to as standard input
The ostream object named cout, also referred to as standard output
The ostream object named cerr, also referred to as standard error
int main()
{
cout << "Please, insert two numbers:" << endl;
float v1, v2;
cout << "The sum of " << v1 << " and " << v2
<< " is " << v1 + v2 << endl;
return 0;
}
The stream operators (<< and >>) are left associative and return the
left operand, i.e. the stream object)
So we can chain the stream operations
int main()
{
const double PI = 3.1415926535897931;
Output:
3.14159
3.14159265358979
3.141592653589793e+00
3.141592653589793
3.14159265358979
Every name in a C++ program must refer to a unique entity (e.g. a variable,
function, type, etc.)
A name can be reused, also with different meanings, as long as it is used in
different context
Such context is the scope, i.e. a region of the program
There are different kinds of scope:
The statements between a pair of matching braces form a scope. The body of
the main or the body of every function and the scopes nested inside a function
(such as a block) form local scopes
Names defined outside any function have global scope. They are accessible
from anywhere in the program
Namespaces partition the global namespace. A namespace is a scope, as we
have already seen with the standard library namespace std
Every class defines its own new scope. An examples is given by the type
size_type of the string class
{
unsigned int s = 1; In this block, s definition
cout << "Inner s: " << s << endl; hides the outer one
}
return 0;
}
Output:
Inner s: 1
Outer s: 0
Global s: ---------
if (i < j)
++i;
do-while statement
double threshold = -1;
do {
cout << "Please enter a threshold level in the range [0, 1]" Statement executed
<< endl; at least once
cin >> threshold;
} while (threshold < 0 || threshold > 1);
int i = 0;
while (i < size) { Recurrent pattern:
// operations that don't
// change the value of i
for loop
++i;
}
range-for statement
for (int x : v) {
sum += x; for each value x in
sum2 += x*x; range v
} C++11
int n = 10;
vector<float> a(n, 5.0); // a has n elements that are copies of 5.0
C++11 vector<int> b = {3,2,7,11,23}; // b contains the elements provided in the list
c = e; // c is now a copy of e
// prepend elements of a in e
e.insert(e.begin(), a.begin(), a.end());
vector<complex<double>> f;
f.push_back({1, -1}); // analogous to push_back(complex<double>(1,-1)), but shorter
// thanks to initializer list
C++11 f.emplace_back(1, -1); // emplace_back is analogous to push_back but it just needs the
// arguments to construct the value, which is created in-place
}
Sometime we need a new name for a type, e.g. because it is too long
or complex or because we need different types to have same name
When we pass built-in types by value, the cost of copying them into the
function parameters is negligible
double sum = 0;
for (const auto& x : samples) each element in samples is
sum += x; passed to x as const reference
return sum/size;
}
The type that we specify for the function argument is called “reference
to const vector of double”
No copy of the actual argument passed with the function call (efficient)
The actual argument is passed as a read-only object
int main()
{
int i = 5, j = 20;
swap(i,j); // After this call: i = 20, j = 5
This function has no return value. Its return type is void, a C/C++ built-
in type used in a few restricted ways, e.g. to name a return type
The purpose of the swap function is to change its argument values. So
its parameters are declared as references
Whenever the function does not need to change the parameter's value,
and the parameter has a type that can be time consuming to copy,
then the parameter should be a const reference