C++ is standardized by an ISO working group.
When you compile the program you can use the flag with specific value std:
-std=c++11
-std=c++14
-std=c++17
Default language standard for compilation depends on the version of g++ compiler.
A namespace provides a way for you to divide your program into different named "spaces".
Within each space you may re-use the names of variables, functions, etc.
Syntax:
namespace Q {
namespace V { ...
}
}
Here we define namespace Q and within it namespace V. You can define variables, function and classes inside the namespaces.
Most important namespace is std it encapsulates all the classes and functions defined by the STL library.
Using-declarations introduces a name that is defined elsewhere into the declarative region where this using-declaration appears.
In other words you need to declare using the namespace to be able to access its elements.
C++ allows you to import namespace via the using statement keywords.
using namespace std;
Ordinarily you can also change names in a namespace by prefixing them with the name of their namespace and two colons (::). For example, to declare a variable as a list you would write:
std::list<int> intList;
Polymorphism means one thing in many form.
Polymorphism enables one common interface for many implementations, and for objects to act differently under different circumstances
Single operator behave different for different data type. Example: addition operator use to add integer and concatenate for string.
Static polymorphism (Compile-time Polymorphism) decides which method to execute during compile time.
In static polymorphism many functions have some differences as number, type, and sequence of arguments.
Example: Function declaration the various types of parameters are specified, and therefore the function can be bound to calls at compile time.
In C++ static polymorphism is obtained through function overloading and operator overloading.
Dynamic polymorphism where an entity can modify its form depending on the situation.
A function is dynamic polymorphism when one function can have more then one form and the call of various form can be resolved at run time dynamically or at the time of execution.
In C++ static polymorphism is obtained through virtual function (we will not discuss virtual functions during this class).
An overloaded declaration is a declaration that is declared with the same name as a previously declared declaration in the same scope, except that both declarations have different arguments and different definition (implementation).
When you call an overloaded function or operator, the compiler determines the most appropriate definition to use.
Overloaded operators are functions with special names the keyword operator followed by the symbol for the operator being defined.
Like any other function, an overloaded operator has a return type and a parameter list.
You can redefine or overload most of the built-in operators available in C++.
Overloaded operators are functions with special function names:
operator X ( )
{
....
}
Where X is any of the 38 operators:
+ - * / % ˆ & | ~ ! = < > += -= *= /= %= ˆ= &= |= << >> >>= <<= == != <= >= && || ++ -- , ->* -> ( ) [ ]
Overloading an operator does not change the precedence of calculations involving the operator, nor does it change the number of operands that the operator uses.
Example:
struct Student {
int nr_index;
float average;
};
bool operator==(const Student &a, const Student &b) {
return a.nr_index==b.nr_index;
}
bool operator< ( Student const &a, Student const &b) const {
return a.average < b.average;
}
We can define an overloading operator as a member of a struct (class), then it takes one argument, or outside - nonmember, then it will take two arguments.
struct Distance {
int meters;
int cm;
bool operator<(const MyStruct& rhs) const
{
if (meters < rhs.meters)
return true;
else
if (cm < rhs.cm)
return true;
}
}
Overloading comparison operator is necessary to be able to sort() structures.
The stream insertion and stream extraction operators also can be overloaded to perform input and output for user-defined types like an object.
struct Distance {
int meters;
int cm;
};
std::ostream & operator <<( std::ostream & output, const Distance & D ) {
output << "M : " << D.meters << " Cm : " << D.cm;
return output;
}
The Three Basic Rules of Operator Overloading in C++:
1. Whenever the meaning of an operator is not obviously clear and undisputed, it should not be overloaded. Instead, provide a function with a well-chosen name.2. Always stick to the operator’s well-known semantics.3. Always provide all out of a set of related operations (if your type supports a + b, users will expect to be able to call a += b, too.)
Operator overloading allows you to redefine the way operator works for user-defined types only (objects, structures). It cannot be used for built-in types (int, float, char etc.).
Two operators = and & (address) are already overloaded by default in C++. For example: To copy objects of same class, you can directly use = operator. You do not need to create an operator function.
Operator overloading cannot change the precedence and associativity of operators.
There are 4 operators that cannot be overloaded in C++. They are :: (scope resolution), . (member selection), .* (member selection through pointer to function) and ?: (ternary operator).
Generic programming means that you are not writing source code that is compiled as-is but that you write "templates" of source codes that the compiler in the process of compilation transforms into source codes.
For example you define a type List without saying which type is collected in the list.
So called generic types are elements of almost every modern object oriented programming language.
C++ uses templates to enable generic programming techniques.
In the context of C++ generic elements of programs are evaluated at compile time.
Generics are used to generate short, simple code and to avoid duplication of code,
With templates, programmers can define a family of functions or classes that can perform operations on different types of data.
Templates are widely used to implement the Standard Template Library (STL).
A function template is a function which contains generic code to operate on different types of data.
This enables a programmer to write functions without having to specify the exact type of parameters.
To define template we use keyword template followed by generic type names.
template<class Type, ...>
return–type function–name(Type arg1, ...)
{
//Body of function template
}
#include <iostream>
using namespace std;
template<class Type>
void summ(Type x, Type y)
{
cout<<“Sum is: “<<x+y<<endl;
}
int main()
{
int a = 10, b = 20;
summ(a, b);
float p = 1.5, q = 2.4;
summ(p, q);
return 0;
}
Output:
Sum is: 30
Sum is: 3.9
In the above program compiler generates two copies of the above function template. One for int type arguments and the other for float type arguments.
Every template data type (or generic data type) should be used as types in the function template definition as type of parameters.
Wrong:
template<class Type>
void summ(int x, int y)
Use all template data types.
Wrong:
template<class Type1, class Type2>
void summ(Type1 x, int y) //Error since Type2 is not used
A template parameter pack (...) is a template parameter that accepts zero or more template arguments.
Example:
template<class ... Types> struct Tuple {};
Tuple<> t0; // Types contains no arguments
Tuple<int> t1; // Types contains one argument: int
Tuple<int, float> t2; // Types contains two arguments: int and float
For functions, a function with three dots means, that you can pass any number of variables as arguments.
void func(unsigned int n_args, int arg, ...)
{
for(unsigned int i = 0; i < n_args; ++i)
cout << *((int*)&arg + i) << ' ';
}
template<typename T>
T adder(T v) {
return v;
}
template<typename T, typename... Args>
T adder(T first, Args... args) {
return first + adder(args...);
}
And here are a couple of ways we could call it:
long sum = adder(1, 2, 3, 8, 7);
std::string s1 = "x", s2 = "aa", s3 = "bb", s4 = "yy";
std::string ssum = adder(s1, s2, s3, s4);
Templates are generic because the compiler translates the template into actual code.
To instantiate a template, compilers substitute specific arguments for a template's parameters to generate a concrete function or class instance.
You can use templates to perform operations during compilation.
Sometimes called anonymous functions.
Example:
[](int x, int y) -> int { return x + y; }
Unnamed function that take two integers and returns its sum.
Example:
// generic lambda, operator() is a template with two parameters
auto glambda = [](auto a, auto&& b) { return a < b; };
bool b = glambda(3, 3.14); // ok
Lambda expression are defined with [] that are followed by the list of arguments and -> on the right side you put the returning type and the body of the function.
[]()->int { return 123; };
is equivalent to :
int funkcja()
{
return 123;
}
To create function "in place" in order to make code more clear and easier to maintain.
Example:
std::sort( vector.begin(), vector.end(),[]( const int & a, const int & b )->bool { return a > b; } );
Or
std::for_each(v.begin(), v.end(), [](int) { /* do something here*/ });
Exceptions provide a way to react to exceptional circumstances (like runtime errors) in programs by transferring control to special functions called handlers.
we say the exceptio is thrown and afterwards caught by the exception handler.
The exception causes the current scope to be exited, and also each outer scope (propagation) until a suitable handler is found.
The exception-causing code is placed inside a try block. The exceptions are handled in separate catch blocks (the handlers); each try block can have multiple exception handlers.
If no exception is thrown, the code continues normally and all handlers are ignored.
You define try...catch block with keywords try and catch
try
{
....
}
catch ()
{
.....
}
The C++ Standard library provides a declaration of objects to be thrown as exceptions. It is called std::exception and is defined in the <exception> header.
Exceptions can be thrown anywhere within a code block using throw statement.
throw param;
Param can be an object of any type.
throw 0;
throw std::out_of_range ("description");
You can specify what type of exception you want to catch in the catch statement (they have to match type given in throw).
You can use ... to catch any exception
catch(...)
#include <stdexcept>
int main() {
try {
std::vector<int> vec{3, 4, 3, 1};
int i = vec.at(4); // Throws an exception, std::out_of_range (indexing for vec is from 0-3 not 1-4)
}
// An exception handler, catches std::out_of_range, which is thrown by vec.at(4)
catch (std::out_of_range &e) {
std::cerr << "Accessing a non-existent element: " << e.what() << '\n';
}
// To catch any other standard library exceptions (they derive from std::exception)
catch (std::exception &e) {
std::cerr << "Exception thrown: " << e.what() << '\n';
}
// Catch any unrecognised exceptions (i.e. those which don't derive from std::exception)
catch (...) {
std::cerr << "Some fatal error\n";
}
}
Functions/Methods can handle any exceptions they choose
Separation of Error Handling code from Normal Code.
You can easily report error to the program user.
Exceptions have efficient implementation in modern C++.
Using exceptions for error handling makes your code simpler, cleaner, and less likely to miss errors.
Newest, just published (december 2017), standard for C++.
Draft version published in March 2017.
Official list of changes :
A file system library based on boost::filesystem.
The library is located in the <filesystem> header. It uses namespace std::filesystem.
Datatype to store data of any type, "python - like".
A better way to handle any type and replace void*.
"The discriminated type may contain values of different types but does not attempt conversion between them".
auto a = std::any(12);
a = std::string("hello world");
a = 10.0f;
When you want to read a value you have to perform a proper cast:
auto a = std::any(12);
std::cout << std::any_cast<int>(a) << '\n';
Optional data type means allow a variable to bo empty or store a value.
Example:
std::optional<std::string> ostr = GetUserResponse();
if (ostr)
ProcessResponse(*ostr);
else
Report("please enter a valid value");
https://en.wikipedia.org/wiki/C%2B%2B
http://www.bfilipek.com/2017/09/cpp17-details-utils.html
https://isocpp.org/files/papers/p0636r0.html
http://www.bfilipek.com/2017/08/cpp17-details-filesystem.html
http://en.cppreference.com/w/cpp/language/namespace