2:15-7
Session recap
Functional programming(FP)
Functional programming paradigm exits for several decades but only entered the industry when Erlang was used for the Ericsson phones, somewhere in the late 1980s (arguably there can be found some Lisp commercial products )
There are many functional languages, the most clean and less likely to be used in the industry (but is considered the flagship of FP is
Haskell but there are many others such as MS F# , OCamel, ML etc, of which some are becoming really popular because they run on the Java Virtual Machine such as Scala, Scheme and Clojure.
Functional programming adheres to Lambda Calculus, a formal system to express computation
Of course many other multi-paradigm languages support FP (either partially or fully), such as Python, Ruby, Perl and even C++.
Reinterpret_cast<Type> ???
If I understood correctly you wanted to know what the reinterpret_cast is for.
We called std::istream method read which has the following signature
istream& read (char* s, streamsize n);
Notice that the first argument requires a char* (a Pointer to array of characters) and we had a pointer to unsigned short, we needed to cast it from pointer to unsigned short to pointer to character.
In C we have only one type of casting operator, marked in green
int a = 1;
double d = (double)a;
int *pI = &a;
double *pD = (double*)pI;
C++ casts
C Cast is still supported in c++ but In C++ there are additional 4 different cast operators
Why?
- C Cast is not easy to search for textually
- The C cast operator is dangerous
- It's incompatible with some C++ concepts (Multiple inheritance)
- It doesn't make distinction between different types of casting.
The 4 C++ casts are
- static_cast - Generic kind of cast (closest to C cast)
- dynamic_cast - The cast is performed during runtime
- const_cast - removes const-ness of a type
- reinterpret_cast - Tells the compiler to consider a pointer or a reference to be of another type
See more next pages
static_cast
- Convert pointer of base class to pointer of derived
- General conversions (i.e. int to float etc
int i = 7;
double d = static_cast<double>(i); // Compiler will change the bit representation
class Base {}
class Derived : public Base {}
Derived d;
Base b = static_cast<Base>(d); // Up cast
Base* pB = new Derived();
Derived* pD = static_cast<Derived*>(pB); // May be risky if pB is not Derived
std::string s = static_cast<string>("Some text"); // Compiler will actually call constructor
Static cast may generate some code, it is mostly safe except when a Base class pointer is cast to a derived class pointer.
Down cast is not allowed in virtual base classes
Dynamic_cast
Used for down casting a reference or a pointer to a more specific type in the class hierarchy. Type safety check is performed on runtime and if the types are incompatible an exception is thrown. Require Runtime Type Information (RTTI)
class Base {};
class DerivedLeft : virtual Base {};
class DerivedRight : virtual Base {};
class Derived : public DerivedLeft, public DerivedRight;
Base* pB = new Derivde();
DerivedLeft* pDL = dynamic_cast<DerivedLeft*>(pB);
const_cast
C cast operator can easily remove const-ness even when we don't intend to
void foo(const unsigned short* buffer)
{
char* pC = (char*)buffer; // The const was removed
....
}
But, const is usually there for a reason and removing it is usually due to social circumstances and not the regular modus operadi, thus, other cast operator are not allowed to remove const-ness and this new cast was introduced
void foo(const unsigned short* buffer)
{
char* pC = const_cast<char*>(buffer); // Performed explicitly. So probably that's what we want
....
}
reinterpret_cast
Sometimes we are required to use a reference or a pointer of a specific type while we have another type altogether, just like in our ifstream::read that expects a char* while we have unsigned short*.
reinterpret_cast, tells the compiler to ignore the type system and just consider the pointer(or reference) to be of a different type.
This may is a risky cast, it subvert the type system and the responsibility for correctness lies on the programmer.
int* pI= new int[10];
double* pD = reinterpret_cast<double*>(pI);
The above example, while syntactically correct, is very likely a bug.
Operator () - Accessing matrix elements
I wanted to mention that if we would like to access the 3D matrix using its coordinates instead of repeating the formula we can implement
template <class T>
class Matrix {
...
T& operator(size_t h, size_t w, size_t d) const { ... };
};
Martix<unsigned short> m(HEIGHT, WIDTH, DEPTH);
cout << m(10, 11, 12) << endl; // Display element at (10, 11, 12)
m(10, 11, 12) = 100; // Assign that element a different value.
Input Iterators
As we already mentioned that, I will commit it to a slide
How to read entire file to a vector?
#include <vector>
#include <iterator> // for input_iterator and output_iterator
fstream file("FileName", fstream::in | fstream::binary); // Flags may differ
vector<unsigned short> vec(istream_iteator<unsigned short>(file), istream_iterator<unsigned short>());
file.close();
The above will read into vec the entire file. However, vec is a new declared vector, what if we already have an empty vector?
#include <vector>
#include <algorithm> // For copy
#include <iterator> // for input_iterator and output_iterator
vector<unsigned short> vec;
fstream file("FileName", fstream::in | fstream::binary); // Flags may differ
copy(istream_iteator<unsigned short>(file), istream_iterator<unsigned short>(), back_inserter(vec));
file.close();
We probably need to clarify that in next session.
Output iterators
So we can read a file to a vector, what about write a vector to a file?
#include <iterator> // For output_iterator
#include <algorithm> // For copy
fstream file("filename", ios::out | ios::binary);
copy(vec.begin(), vec.end(), ostream_iterator<unsigned short>(file));
file.close();
2:15-7
By perplexedpigmy
2:15-7
- 1,076