diff options
| author | Jonathan Scott Duff <duff@pobox.com> | 2015-06-25 22:58:56 -0500 | 
|---|---|---|
| committer | Jonathan Scott Duff <duff@pobox.com> | 2015-06-25 22:58:56 -0500 | 
| commit | 2162639cd901a81a24eb4a566ba5108da87634cf (patch) | |
| tree | 3bef6c762bcc04609e0a6cb219c3c169e5aa5748 /c++.html.markdown | |
| parent | 041064416115985ef336babe6ef7dbac726327fa (diff) | |
| parent | ef771384ae672e341ec309cf71cf372143607892 (diff) | |
Merge remote-tracking branch 'upstream/master'
Conflicts:
	perl6.html.markdown
Diffstat (limited to 'c++.html.markdown')
| -rw-r--r-- | c++.html.markdown | 149 | 
1 files changed, 138 insertions, 11 deletions
| diff --git a/c++.html.markdown b/c++.html.markdown index 1a84efa4..ff2a98fd 100644 --- a/c++.html.markdown +++ b/c++.html.markdown @@ -32,8 +32,7 @@ one of the most widely-used programming languages.  // variable declarations, primitive types, and functions.  // Just like in C, your program's entry point is a function called -// main with an integer return type, -// though void main() is also accepted by most compilers (gcc, clang, etc.) +// main with an integer return type.  // This value serves as the program's exit status.  // See http://en.wikipedia.org/wiki/Exit_status for more information.  int main(int argc, char** argv) @@ -289,7 +288,7 @@ public:      // Functions can also be defined inside the class body.      // Functions defined as such are automatically inlined. -    void bark() const { std::cout << name << " barks!\n" } +    void bark() const { std::cout << name << " barks!\n"; }      // Along with constructors, C++ provides destructors.      // These are called when an object is deleted or falls out of scope. @@ -301,7 +300,7 @@ public:  }; // A semicolon must follow the class definition.  // Class member functions are usually implemented in .cpp files. -void Dog::Dog() +Dog::Dog()  {      std::cout << "A dog has been constructed\n";  } @@ -324,7 +323,7 @@ void Dog::print() const      std::cout << "Dog is " << name << " and weighs " << weight << "kg\n";  } -void Dog::~Dog() +Dog::~Dog()  {      cout << "Goodbye " << name << "\n";  } @@ -333,7 +332,7 @@ int main() {      Dog myDog; // prints "A dog has been constructed"      myDog.setName("Barkley");      myDog.setWeight(10); -    myDog.printDog(); // prints "Dog is Barkley and weighs 10 kg" +    myDog.print(); // prints "Dog is Barkley and weighs 10 kg"      return 0;  } // prints "Goodbye Barkley" @@ -342,7 +341,7 @@ int main() {  // This class inherits everything public and protected from the Dog class  class OwnedDog : public Dog { -    void setOwner(const std::string& dogsOwner) +    void setOwner(const std::string& dogsOwner);      // Override the behavior of the print function for all OwnedDogs. See      // http://en.wikipedia.org/wiki/Polymorphism_(computer_science)#Subtyping @@ -426,7 +425,7 @@ int main () {      Point up (0,1);      Point right (1,0);      // This calls the Point + operator -    // Point up calls the + (function) with right as its paramater +    // Point up calls the + (function) with right as its parameter      Point result = up + right;      // Prints "Result is upright (1,1)"      cout << "Result is upright (" << result.x << ',' << result.y << ")\n"; @@ -434,6 +433,85 @@ int main () {  }  ///////////////////// +// Templates +///////////////////// + +// Templates in C++ are mostly used for generic programming, though they are +// much more powerful than generics constructs in other languages. It also +// supports explicit and partial specialization, functional-style type classes, +// and also it's Turing-complete. + +// We start with the kind of generic programming you might be familiar with. To +// define a class or function that takes a type parameter: +template<class T> +class Box { +public: +    // In this class, T can be used as any other type. +    void insert(const T&) { ... } +}; + +// During compilation, the compiler actually generates copies of each template +// with parameters substituted, and so the full definition of the class must be +// present at each invocation. This is why you will see template classes defined +// entirely in header files. + +// To instantiate a template class on the stack: +Box<int> intBox; + +// and you can use it as you would expect: +intBox.insert(123); + +// You can, of course, nest templates: +Box<Box<int> > boxOfBox; +boxOfBox.insert(intBox); + +// Up until C++11, you must place a space between the two '>'s, otherwise '>>' +// will be parsed as the right shift operator. + +// You will sometimes see +//   template<typename T> +// instead. The 'class' keyword and 'typename' keyword are _mostly_ +// interchangeable in this case. For full explanation, see +//   http://en.wikipedia.org/wiki/Typename +// (yes, that keyword has its own Wikipedia page). + +// Similarly, a template function: +template<class T> +void barkThreeTimes(const T& input) +{ +    input.bark(); +    input.bark(); +    input.bark(); +} + +// Notice that nothing is specified about the type parameters here. The compiler +// will generate and then type-check every invocation of the template, so the +// above function works with any type 'T' that has a const 'bark' method! + +Dog fluffy; +fluffy.setName("Fluffy") +barkThreeTimes(fluffy); // Prints "Fluffy barks" three times. + +// Template parameters don't have to be classes: +template<int Y> +void printMessage() { +  cout << "Learn C++ in " << Y << " minutes!" << endl; +} + +// And you can explicitly specialize templates for more efficient code. Of +// course, most real-world uses of specialization are not as trivial as this. +// Note that you still need to declare the function (or class) as a template +// even if you explicitly specified all parameters. +template<> +void printMessage<10>() { +  cout << "Learn C++ faster in only 10 minutes!" << endl; +} + +printMessage<20>();  // Prints "Learn C++ in 20 minutes!" +printMessage<10>();  // Prints "Learn C++ faster in only 10 minutes!" + + +/////////////////////  // Exception Handling  ///////////////////// @@ -441,12 +519,13 @@ int main () {  // (see http://en.cppreference.com/w/cpp/error/exception)  // but any type can be thrown an as exception  #include <exception> +#include <stdexcept>  // All exceptions thrown inside the _try_ block can be caught by subsequent  // _catch_ handlers.  try {      // Do not allocate exceptions on the heap using _new_. -    throw std::exception("A problem occurred"); +    throw std::runtime_error("A problem occurred");  }  // Catch exceptions by const reference if they are objects  catch (const std::exception& ex) @@ -537,7 +616,7 @@ void doSomethingWithAFile(const char* filename)  {      FILE* fh = fopen(filename, "r"); // Open the file in read mode      if (fh == nullptr) -        throw std::exception("Could not open the file."); +        throw std::runtime_error("Could not open the file.");      try {          doSomethingWithTheFile(fh); @@ -586,8 +665,56 @@ void doSomethingWithAFile(const std::string& filename)  //   vector (i.e. self-resizing array), hash maps, and so on  //   all automatically destroy their contents when they fall out of scope.  // - Mutexes using lock_guard and unique_lock + + +///////////////////// +// Fun stuff +///////////////////// + +// Aspects of C++ that may be surprising to newcomers (and even some veterans). +// This section is, unfortunately, wildly incomplete; C++ is one of the easiest +// languages with which to shoot yourself in the foot. + +// You can override private methods! +class Foo { +  virtual void bar(); +}; +class FooSub : public Foo { +  virtual void bar();  // overrides Foo::bar! +}; + + +// 0 == false == NULL (most of the time)! +bool* pt = new bool; +*pt = 0;  // Sets the value points by 'pt' to false. +pt = 0;  // Sets 'pt' to the null pointer. Both lines compile without warnings. + +// nullptr is supposed to fix some of that issue: +int* pt2 = new int; +*pt2 = nullptr;  // Doesn't compile +pt2 = nullptr;  // Sets pt2 to null. + +// But somehow 'bool' type is an exception (this is to make `if (ptr)` compile). +*pt = nullptr;  // This still compiles, even though '*pt' is a bool! + + +// '=' != '=' != '='! +// Calls Foo::Foo(const Foo&) or some variant copy constructor. +Foo f2; +Foo f1 = f2; + +// Calls Foo::Foo(const Foo&) or variant, but only copies the 'Foo' part of +// 'fooSub'. Any extra members of 'fooSub' are discarded. This sometimes +// horrifying behavior is called "object slicing." +FooSub fooSub; +Foo f1 = fooSub; + +// Calls Foo::operator=(Foo&) or variant. +Foo f1; +f1 = f2; +  ``` -Futher Reading: +Further Reading:  An up-to-date language reference can be found at  <http://cppreference.com/w/cpp> | 
