C++ is not complicated.
The problem is. C++ is taught in a wrong way.
The problem is. C++ is taught in a wrong way.
C++ is often perceived not only as a generic, high-performance language but also perceived as the descendant of the low-level language C.
Therefore most introductory courses cover the traits of C and the inner workings of the machine.
In my opinion, this has no place in beginner course.
In my opinion, this has no place in beginner course.
So in my opinion any course should start along the following way:
Variables, Values(types), Control-flow and functions
This maps almost 1:1 to any procedural language e.g. JavaScript.
As pointers and references have no value-semantics their introduction should be postponed until a problem motivated use-case occur.
Arrays, Data Structures and Algorithms
Skip plain (stack-)arrays because they have no value-semantics and are error-prone.
Go straight to std::vector. Here you can introduce yourself to the merits of for_each, iterators and range-based-for loops - this is a good place to motivate the use of lambdas.
This compares well to the functional style of languages like JavaScript and Python.
This compares well to the functional style of languages like JavaScript and Python.
Next on the roadmap could be simple structs(PODs) and (std::)maps as a method to manage data.
As swapping of variables is part of many (inplace-)algorithms, references and pass by reference are worth a look.
Techniques to add syntactic sugar via operator overloading, constructors are useful and should be taught along with the Rule of three (C++ programming).
Templates, decltype & auto
Templates should be just seen as a way to generalize functions and struct(classes).
C++11/14 introduces the possibility to write robust and generic code.
Furthermore it obsoletes constructs like:
Furthermore it obsoletes constructs like:
std::vector<float>::const_iterator it = myFloatVector.begin();
Function-definitions and function-overloading can be simplified, especially when templates are used.
Simple function sfinae can also be visited in this context:
- template<class T>
- auto getSize(T data) -> decltype( data.size() ){
- return data.size();
- }
- template<class T>
- auto getSize(T data){
- return 0;
- }
- vector<int> x;
- int y;
- cout << getSize(x) << endl;
- cout << getSize(y) << endl;
Resource-managment and Smartpointers
new & delete should be seen as a method to extend the lifetime of objects across the scope-bounds and to dynamic sized arrays.
new&delete should be seen as a implementation detail.
make_unique and make_shared should be favored.
Implementing std::vector may be a good exercise, introducing to RAII and smartpointers.
Implementing std::vector may be a good exercise, introducing to RAII and smartpointers.
Classes, Inheritance and Type-erasure
In the context of managing heterogeneous datasets (data of different type) in maps and vectors. the topic of polymorphic classes can be visited.
Inheritance and virtual functions should be seen as an implementation detail and therefore hidden via a Type-erased container.
Important things I've omitted:
Things also important but orthogonal to the "core-language"
- preprocessor, transition units & build-scripts
- compilers and flags
- testing & mocking
- preprocessor, transition units & build-scripts
- compilers and flags
- testing & mocking
Follow ups:
- promises(futures) & std::async
- try-catch & exception-safety
- lists vs vectors:
- sfinae with type_traits
- try-catch & exception-safety
- lists vs vectors:
- sfinae with type_traits
Why no raw pointers
The usage of raw pointers is error-prone and often not necessary.
Raw pointers do not display ownership (who is obligated to delete?) and makes harder to reason about code.
Furthermore it does not provide security on the API / type-system level, which requires often checks for null pointer in runtime.
Raw pointers do not display ownership (who is obligated to delete?) and makes harder to reason about code.
Furthermore it does not provide security on the API / type-system level, which requires often checks for null pointer in runtime.
Rule of thumb:
When a function/method doesn't force a shift in an object's ownership, use a reference;
when it does - use a smart pointer.
When a function/method doesn't force a shift in an object's ownership, use a reference;
when it does - use a smart pointer.
Personal note:
Beginners, when introduced to early, often start to randomly permutate * , & or cast-operators. If you introduce pointers at a later stage, it doesn't happen that often because they become more familiar with the type-system.
Beginners, when introduced to early, often start to randomly permutate * , & or cast-operators. If you introduce pointers at a later stage, it doesn't happen that often because they become more familiar with the type-system.
Edit - how to package material:
When teaching C++ I found it to be very engaging when making the examples visual. Programming is more interesting if you can use your every newly learned skill to make *cool* things. Animating a circle to move from left to right without a loop is quite tedious but becomes very easy once you know how to use loops.
Edit2 - managing packages is hard:
Unlike languages like Node or Python, C++ does not have a defacto-standard package-manager. This makes integrating other libraries and writing more high-level code more difficult.
Luckily there are a couple package managers out there:
أضف تعليق:
0 comments: