├── LICENSE ├── Makefile ├── README.html ├── README.rst ├── exam.html ├── exam.rst ├── exam ├── Makefile ├── exam-1 ├── exam-1.cc ├── exam-10 ├── exam-10.cc ├── exam-2 ├── exam-2.cc ├── exam-3 ├── exam-3.cc ├── exam-4 ├── exam-4.cc ├── exam-5 ├── exam-5.cc ├── exam-6 ├── exam-6.cc ├── exam-7 ├── exam-7.cc ├── exam-8 ├── exam-8.cc ├── exam-9 └── exam-9.cc ├── page.tmpl ├── pygment.css ├── rst2html.py ├── sources ├── .DS_Store ├── Makefile ├── crash-course-2.1.cc ├── crash-course-2.2.cc ├── crash-course-2.3.cc ├── crash-course-2.4.cc ├── crash-course-2.5.cc ├── crash-course-2.6.cc ├── crash-course-3.1.cc ├── crash-course-3.2.cc ├── crash-course-3.3.cc ├── crash-course-3.4.cc ├── crash-course-3.5.cc ├── crash-course-4.1.cc ├── crash-course-4.2.cc ├── crash-course-4.3.cc ├── crash-course-4.4.cc ├── crash-course-4.5.cc ├── crash-course-5.1.cc ├── crash-course-5.2.cc ├── crash-course-5.3.cc └── crash-course-5.4.cc └── stylesheet.css /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Nicolas P. Rougier 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | MAKE = /usr/bin/make 2 | RST2HTML = ./rst2html.py 3 | STYLESHEET = stylesheet.css 4 | RST2HTML_OPTIONS = --strip-comments \ 5 | --report=3 \ 6 | --section-numbering \ 7 | --no-toc-backlinks \ 8 | --template=page.tmpl \ 9 | --cloak-email-addresses \ 10 | --stylesheet=$(STYLESHEET) \ 11 | --link-stylesheet 12 | 13 | SOURCES = $(wildcard *.rst) 14 | OBJECTS = $(subst .rst,.html, $(SOURCES)) 15 | 16 | all: $(OBJECTS) pygment.css 17 | 18 | #pygment.css: 19 | # @pygmentize -S tango -f html > pygment.css 20 | 21 | %.html: %.rst Makefile 22 | @echo " - $@" 23 | @$(RST2HTML) $(RST2HTML_OPTIONS) $< $@ 24 | 25 | clean: 26 | @-rm -f $(OBJECTS) 27 | 28 | distclean: clean 29 | @-rm -f `find . -name "*~"` 30 | 31 | .PHONY: all home clean distclean 32 | -------------------------------------------------------------------------------- /README.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 |Author: | 19 |Nicolas P. Rougier |
---|---|
Sources: | crash-course.rst | 21 |
This is an introduction to C++ for C programmers:
94 |If you can't understand the code below, you'd better start with a C tutorial.
96 |97 | #include <stdio.h> 98 | 99 | void main (int argc, char **argv) 100 | { 101 | printf("Hello World!\n"); 102 | } 103 |104 |
If you don't know what are the stack and the heap, you'd better have a look at 106 | some architecture & system introduction.
107 |If you know java, that might help a bit.
109 |If you think python is cool, you're right, but 111 | still, this is not the place.
112 |If you never heard about Bjarne Stroustrup, you might be at the right place.
114 |Here is a list of C++ specific keywords:
116 |117 | asm dynamic_cast namespace reinterpret_cast try 118 | bool explicit new static_cast typeid 119 | catch false operator template typename 120 | class friend private this using 121 | const_cast inline public throw virtual 122 | delete mutable protected true wchar_t 123 |124 |
Even if C++ is slanted toward object-oriented programming (OOP), you can 130 | nevertheless use any c++ compiler to compile c code and benefits from some c++ 131 | goodies.
132 |Prefer the use of <iostream> for input/output operations (see stream 135 | section for explanation).
136 |137 | #include <iostream> 138 | 139 | int main (int argc, char **argv) 140 | { 141 | int i; 142 | std::cout << "Please enter an integer value: "; 143 | std::cin >> i; 144 | std::cout << "The value you entered is " << i << std::endl; 145 | return 0; 146 | } 147 |148 |
The new and delete keywords are used to allocate and free memory. They 152 | are "object-aware" so you'd better use them instead of malloc and 153 | free. In any case, never cross the streams (new/free or malloc/delete).
154 |155 | int *a = new int; 156 | delete a; 157 | 158 | int *b = new int[5]; 159 | delete [] b; 160 |161 |
delete does two things: it calls the destructor and it deallocates the 162 | memory.
163 |A reference allows to declare an alias to another variable. As long as the 167 | aliased variable lives, you can use indifferently the variable or the alias.
168 |169 | int x; 170 | int& foo = x; 171 | 172 | foo = 42; 173 | std::cout << x << std::endl; 174 |175 |
References are extremely useful when used with function arguments since it 176 | saves the cost of copying parameters into the stack when calling the function.
177 |You can specify default values for function parameters. When the function is 181 | called with fewer parameters, default values are used.
182 |183 | float foo( float a=0, float b=1, float c=2 ) 184 | {return a+b+c;} 185 | 186 | cout << foo(1) << endl 187 | << foo(1,2) << endl 188 | << foo(1,2,3) << endl; 189 |190 |
You should obtain values 4, 5 and 6.
191 |Namespace allows to group classes, functions and variable under a common scope 195 | name that can be referenced elsewhere.
196 |197 | namespace first { int var = 5; } 198 | namespace second { int var = 3; } 199 | cout << first::var << endl << second::var << endl; 200 |201 |
You should obtain values 3 and 5. There exists some standard namespace in the 202 | standard template library such as std.
203 |Function overloading refers to the possibility of creating multiple functions 207 | with the same name as long as they have different parameters (type and/or 208 | number).
209 |210 | float add( float a, float b ) 211 | {return a+b;} 212 | 213 | int add( int a, int b ) 214 | {return a+b;} 215 |216 |
It is not legal to overload a function based on the return type (but you can do it 217 | anyway)
218 |Defines and macros are bad if not used properly as illustrated below
222 |223 | #define SQUARE(x) x*x 224 | 225 | int result = SQUARE(3+3); 226 |227 |
For constants, prefer the const notation:
228 |229 | const int two = 2; 230 |231 |
For macros, prefer the inline notation:
232 |233 | int inline square(int x) 234 | { 235 | return x*x; 236 | } 237 |238 |
242 | #ifdef __cplusplus 243 | extern "C" { 244 | #endif 245 | 246 | #include "some-c-code.h" 247 | 248 | #ifdef __cplusplus 249 | } 250 | #endif 251 | 252 |253 |
Write a basic makefile for compiling sources
258 |solution: Makefile
259 |How would you declare:
261 |264 |274 |265 |
272 |- A pointer to a char
266 |- A constant pointer to a char
267 |- A pointer to a constant char
268 |- A constant pointer to a constant char
269 |- A reference to a char
270 |- A reference to a constant char
271 |solution: crash-course-2.1.cc
273 |
279 | solution: crash-course-2.2.cc280 |
284 | solution: crash-course-2.3.cc285 |
Is this legal ?
287 |288 | int add( int a, int b ) { return a+b; } 289 | 290 | int add( int a, int b, int c=0 ) { return a+b+c; } 291 |292 |
295 | solution: crash-course-2.4.cc296 |
300 | solution: crash-course-2.5.cc301 |
306 | solution: crash-course-2.6.cc307 |
A class migh be considered as an extended concept of a data structure: instead 312 | of holding only data, it can hold both data and functions. An object is an 313 | instantiation of a class. By default, all attributes and functions of a class 314 | are private (see below Access control). If you want a public default behavior, 315 | you can use keyword struct instead of keyword class in the declaration.
316 |317 | class Foo { 318 | int attribute; 319 | int function( void ) { }; 320 | }; 321 | 322 | struct Bar { 323 | int attribute; 324 | int function( void ) { }; 325 | }; 326 | 327 | Foo foo; 328 | foo.attribute = 1; // WRONG 329 | 330 | Bar bar; 331 | bar.attribute = 1; // OK 332 | 333 |334 |
It is possible to specify zero, one or more constructors for the class.
337 |338 | #include <iostream> 339 | 340 | class Foo { 341 | public: 342 | Foo( void ) 343 | { std::cout << "Foo constructor 1 called" << std::endl; } 344 | Foo( int value ) 345 | { std::cout << "Foo constructor 2 called" << std::endl; } 346 | }; 347 | 348 | int main( int argc, char **argv ) 349 | { 350 | Foo foo_1, foo_2(2); 351 | return 0; 352 | } 353 |354 |
There can be only one destructor per class. It takes no argument and returns 358 | nothing.
359 |360 | #include <iostream> 361 | 362 | class Foo { 363 | public: 364 | ~Foo( void ) 365 | { std::cout << "Foo destructor called" << std::endl; } 366 | } 367 | int main( int argc, char **argv ) 368 | { 369 | Foo foo(); 370 | return 0; 371 | } 372 |373 |
Note that you generally never need to explicitly call a destructor.
374 |You can have fine control over who is granted access to a class function or 378 | attribute by specifying an explicit access policy:
379 |Object's member should be initialized using initialization lists
388 |389 | class Foo 390 | { 391 | int _value; 392 | public: 393 | Foo(int value=0) : _value(value) { }; 394 | }; 395 |396 |
It's cheaper, better and faster.
397 |401 | class Foo { 402 | private: 403 | int _value; 404 | 405 | public: 406 | Foo( int value ) : _value(value) { }; 407 | 408 | Foo operator+ ( const Foo & other ) 409 | { 410 | return Foo( _value+ other._value ); 411 | } 412 | 413 | Foo operator* ( const Foo & other ); 414 | { 415 | return Foo( _value * other._value ); 416 | } 417 | } 418 |419 |
Friends are either functions or other classes that are granted privileged 423 | access to a class.
424 |425 | #include <iostream> 426 | 427 | class Foo { 428 | public: 429 | friend std::ostream& operator<< ( std::ostream& output, 430 | Foo const & that ) 431 | { 432 | return output << that._value; 433 | } 434 | private: 435 | double _value; 436 | }; 437 | 438 | int main( int argc, char **argv ) 439 | { 440 | Foo foo; 441 | std::cout << "Foo object: " << foo << std::endl; 442 | return 0 443 | } 444 |445 |
Why the following code doesn't compile ?
450 |451 | class Foo { Foo () { }; }; 452 | 453 | int main( int argc, char **argv ) 454 | { 455 | Foo foo; 456 | } 457 |458 |
solution: crash-course-3.1.cc
459 |Write a Foo class with default and copy constructors and add also an 461 | assignment operator. Write some code to highlight the use of each of them.
462 |solution: crash-course-3.2.cc
463 |Write a Point class that can be constructed using cartesian or polar 465 | coordinates.
466 |solution: crash-course-3.3.cc
467 |Write a Foo class and provide it with an input method.
469 |solution: crash-course-3.4.cc
470 |Is is possible to write something like foo.method1().method2() ?
472 |solution: crash-course-3.5.cc
473 |Inheritance is done at the class definition level by specifying the base class 482 | and the type of inheritance.
483 |484 | class Foo { /* ... */ }; 485 | class Bar_public : public Foo { /* ... */ }; 486 | class Bar_private : private Foo { /* ... */ }; 487 | class Bar_protected : protected Foo { /* ... */ }; 488 |489 |
Bar_public, Bar_private and Bar_protected are derived from Foo. 490 | Foo is the base class of Bar_public, Bar_private and Bar_protected.
491 |A virtual function allows derived classes to replace the implementation 501 | provided by the base class (yes, it is not automatic...). Non virtual methods 502 | are resolved statically (at compile time) while virtual methods are resolved 503 | dynamically (at run time).
504 |505 | class Foo { 506 | public: 507 | Foo( void ); 508 | void method1( void ); 509 | virtual void method2( void ); 510 | }; 511 | 512 | class Bar : public Foo { 513 | public: 514 | Bar( void ); 515 | void method1( void ); 516 | void method2( void ); 517 | }; 518 | 519 | Foo *bar = new Bar(); 520 | bar->method1(); 521 | bar->method2(); 522 |523 |
Make sure your destructor is virtual when you have derived class.
524 |You can define pure virtual method that prohibits the base object to be 528 | instantiated. Derived classes need then to implement the virtual method.
529 |530 | class Foo { 531 | public: 532 | Foo( void ); 533 | virtual void method( void ) = 0; 534 | }; 535 | 536 | class Bar: public Foo { 537 | public: 538 | Foo( void ); 539 | void method( void ) { }; 540 | }; 541 |542 |
A class may inherit from multiple base classes but you have to be careful:
546 |547 | class Foo { protected: int data; }; 548 | class Bar1 : public Foo { /* ... */ }; 549 | class Bar2 : public Foo { /* ... */ }; 550 | class Bar3 : public Bar1, public Bar2 { 551 | void method( void ) 552 | { 553 | data = 1; // !!! BAD 554 | } 555 | }; 556 |557 |
In class Bar3, the data reference is ambiguous since it could refer to 558 | Bar1::data or Bar2::data. This problem is referred as the diamond 559 | problem. You can eliminete the problem by explicitely specifying the data 560 | origin (e.g. Bar1::data) or by using virtual inheritance in Bar1 and Bar2.
561 |Write a Bar class that inherits from a Foo class and makes 566 | constructor and destructor methods to print something when called.
567 |solution: crash-course-4.1.cc
568 |Write a foo function and make it called from a class that has 570 | a foo method.
571 |solution: crash-course-4.2.cc
572 |Write a Real base class and a derived Integer class with all common 574 | operators (+,-,*,/)
575 |solution: crash-course-4.3.cc
576 |Write a Singleton class such that only one object of this class can be 578 | created.
579 |solution: crash-course-4.4.cc
580 |Write a functor class
582 |solution: crash-course-4.5.cc
583 |(by Tim Peters)
592 |593 |615 |594 |614 |Beautiful is better than ugly.595 |Explicit is better than implicit.596 |Simple is better than complex.597 |Complex is better than complicated.598 |Flat is better than nested.599 |Sparse is better than dense.600 |Readability counts.601 |Special cases aren't special enough to break the rules.602 |Although practicality beats purity.603 |Errors should never pass silently.604 |Unless explicitly silenced.605 |In the face of ambiguity, refuse the temptation to guess.606 |There should be one-- and preferably only one --obvious way to do it.607 |Although that way may not be obvious at first unless you're Dutch.608 |Now is better than never.609 |Although never is often better than right now.610 |If the implementation is hard to explain, it's a bad idea.611 |If the implementation is easy to explain, it may be a good idea.612 |Namespaces are one honking great idea -- let's do more of those!613 |
You can catch any exception using the following structure:
619 |620 | try 621 | { 622 | float *array = new float[-1]; 623 | } 624 | catch( std::bad_alloc e ) 625 | { 626 | std::cerr << e.what() << std::endl; 627 | } 628 |629 |
If the raised exception is different from the ones you're catching, program 630 | will stop.
631 |Creating a new exception is quite easy:
635 |636 | #include <stdexcept> 637 | 638 | class Exception : public std::runtime_error 639 | { 640 | public: 641 | Exception() : std::runtime_error("Exception") { }; 642 | }; 643 |644 |
There exist some standard exceptions that can be raised in some circumstances:
648 |#include <stdexcept>
649 |How to handle a constructor that fails ?
673 |solution: crash-course-5.1.cc
674 |Write a program that raise 3 of the standard exceptions.
676 |solution: crash-course-5.2.cc
677 |Write a correct division function.
679 |solution: crash-course-5.3.cc
680 |Write a Integer (positive) class with proper exception handling 682 | (Overflow, Underflow, DivideByZero, etc.)
683 |solution: crash-course-5.4.cc
684 |C++ provides input/output capability throught the iostream classes that provide 691 | the stream concept (iXXXstream for input and oXXXstream for output).
692 |Screen outputs and keyboard inputs may be handled using the iostream header 695 | file:
696 |697 | #include <iostream> 698 | 699 | int main( int argc, char **argv ) 700 | { 701 | 702 | unsigned char age = 65; 703 | std::cout << static_cast<unsigned>(age) << std::endl; 704 | std::cout << static_cast<void const*>(&age) << std::endl; 705 | 706 | double f = 3.14159; 707 | cout.unsetf(ios::floatfield); 708 | cout.precision(5); 709 | cout << f << endl; 710 | cout.precision(10); 711 | cout << f << endl; 712 | cout.setf(ios::fixed,ios::floatfield); 713 | cout << f << endl; 714 | 715 | std::cout << "Enter a number, or -1 to quit: "; 716 | int i = 0; 717 | while( std::cin >> i ) 718 | { 719 | if (i == -1) break; 720 | std::cout << "You entered " << i << '\n'; 721 | } 722 | return 0; 723 | } 724 |725 |
You can implement a class input and output using friends functions:
729 |730 | #include <iostream> 731 | 732 | class Foo { 733 | public: 734 | friend std::ostream& operator<< ( std::ostream & output, Foo const & that ) 735 | { return output << that._value; } 736 | friend std::istream& operator>> ( std::istream & input, Foo& foo ) 737 | { return input >> fred._value; } 738 | 739 | private: 740 | double _value; 741 | }; 742 |743 |
747 | #include <fstream> 748 | 749 | int main( int argc, char **argv ) 750 | { 751 | std::ifstream input( filename ); 752 | // std::ifstream input( filename, std::ios::in | std::ios::binary); 753 | 754 | std::ofstream output( filename ); 755 | // std::ofstream output( filename, std::ios::out | std::ios::binary); 756 | 757 | return 0; 758 | } 759 |760 |
764 | #include <sstream> 765 | 766 | int main( int argc, char **argv ) 767 | { 768 | const char *svalue = "42.0"; 769 | int ivalue; 770 | std::istringstream istream; 771 | std::ostringstream ostream; 772 | 773 | istream.str(svalue); 774 | istream >> ivalue; 775 | std::cout << svalue << " = " << ivalue << std::endl; 776 | 777 | ostream.clear(); 778 | ostream << ivalue; 779 | std::cout << ivalue << " = " << ostream.str() << std::endl; 780 | 781 | return 0; 782 | } 783 |784 |
Templates are special operators that specify that a class or a function is 797 | written for one or several generic types that are not yet known. The format for 798 | declaring function templates is:
799 |You can have several templates and to actually use a class or function 804 | template, you have to specify all unknown types:
805 |806 | template<typename T1> 807 | T1 foo1( void ) { /* ... */ }; 808 | 809 | template<typename T1, typename T2> 810 | T1 foo2( void ) { /* ... */ }; 811 | 812 | template<typename T1> 813 | class Foo3 { /* ... */ }; 814 | 815 | 816 | int a = foo1<int>(); 817 | float b = foo2<int,float>(); 818 | Foo<int> c; 819 |820 |
There are three possible template types:
823 |Type
825 |826 |830 |827 | template<typename T> T foo( void ) { /* ... */ }; 828 |829 |
Non-type
832 |833 |837 |834 | template<int N> foo( void ) { /* ... */ }; 835 |836 |
Template
839 |840 |844 |841 | template< template <typename T> > foo( void ) { /* ... */ }; 842 |843 |
850 | template <class T> 851 | T max( T a, T b) 852 | { 853 | return( a > b ? a : b ); 854 | } 855 | 856 | #include <sstream> 857 | 858 | int main( int argc, char **argv ) 859 | { 860 | std::cout << max<int>( 2.2, 2.5 ) << std::endl; 861 | std::cout << max<float>( 2.2, 2.5 ) << std::endl; 862 | } 863 |864 |
868 | template <class T> 869 | class Foo { 870 | T _value; 871 | 872 | public: 873 | Foo( T value ) : _value(value) { }; 874 | } 875 | 876 | int main( int argc, char **argv ) 877 | { 878 | Foo<int> foo_int; 879 | Foo<float> foo_float; 880 | } 881 |882 |
886 | #include <iostream> 887 | 888 | template <class T> 889 | class Foo { 890 | T _value; 891 | public: 892 | Foo( T value ) : _value(value) 893 | { 894 | std::cout << "Generic constructor called" << std::endl; 895 | }; 896 | } 897 | 898 | template <> 899 | class Foo<float> { 900 | float _value; 901 | public: 902 | Foo( float value ) : _value(value) 903 | { 904 | std::cout << "Specialized constructor called" << std::endl; 905 | }; 906 | } 907 | 908 | int main( int argc, char **argv ) 909 | { 910 | Foo<int> foo_int; 911 | Foo<float> foo_float; 912 | } 913 |914 |
STL containers are template classes that implement various ways of storing 931 | elements and accessing them.
932 |Sequence containers:
933 |Container adaptors:
939 |Associative containers:
945 |See http://www.cplusplus.com/reference/stl/ for more information.
953 |954 | #include <vector> 955 | #include <map> 956 | #include <string> 957 | 958 | int main( int argc, char **argv ) 959 | { 960 | std::vector<int> v; 961 | v.push_back(1); 962 | v.push_back(2); 963 | v.push_back(3); 964 | 965 | std::map<std::string,int> m; 966 | m["one"] = 1; 967 | m["two"] = 2; 968 | m["three"] = 3; 969 | 970 | return 0; 971 | } 972 |973 |
Iterators are a convebient tool to iterate over a container:
977 |978 | #include <map> 979 | #include <string> 980 | #include <iostream> 981 | 982 | int main( int argc, char **argv ) 983 | { 984 | std::map<std::string,int> m; 985 | m["one"] = 1; 986 | m["two"] = 2; 987 | m["three"] = 3; 988 | 989 | std::map<std::string,int>::iterator iter; 990 | for( iter=m.begin(); iter != m.end(); ++iter ) 991 | { 992 | std::cout << "map[" << iter->first << "] = " 993 | << iter->second << std::endl; 994 | } 995 | return 0; 996 | } 997 |998 |
Algorithms from the STL offer fast, robust, tested and maintained code for a lot 1002 | of standard operations on ranged elements. Don't reinvent the wheel !
1003 |Have a look at http://r0d.developpez.com/articles/algos-stl-fr/ (French) and 1004 | http://www.cplusplus.com/reference/algorithm/ for an overview.
1005 |1006 | #include <vector> 1007 | #include <algorithm> 1008 | 1009 | bool compare( const int & first, const int & second ) 1010 | { 1011 | return (first < second); 1012 | } 1013 | 1014 | int main( int argc, char **argv ) 1015 | { 1016 | std::vector<int> v(10); 1017 | std::sort(v.begin(), v.end(), &compare); 1018 | 1019 | return 0; 1020 | } 1021 |1022 |
1026 |1032 |1027 |
1031 |- Write a template stack class using the STL vector class
1028 |- Write a generic vector class with iterators and benchmark it againt the STL 1029 | vector class
1030 |