diff options
Diffstat (limited to 'c++.html.markdown')
| -rw-r--r-- | c++.html.markdown | 781 | 
1 files changed, 511 insertions, 270 deletions
diff --git a/c++.html.markdown b/c++.html.markdown index 7609dd46..50de5eff 100644 --- a/c++.html.markdown +++ b/c++.html.markdown @@ -3,347 +3,588 @@ language: c++  filename: learncpp.cpp  contributors:      - ["Steven Basart", "http://github.com/xksteven"] +    - ["Matt Kline", "https://github.com/mrkline"]  lang: en  --- -I am writing this to highlight the differences and  -additions that C++ has with respect to C. My  -suggestion would be to follow the C tutorial first -then look here for the additions and differences. +C++ is a systems programming language that, +[according to its inventor Bjarne Stroustrup](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Keynote), +was designed to + +- be a "better C" +- support data abstraction +- support object-oriented programming +- support generic programming + +Though its syntax can be more difficult or complex than newer languages, +it is widely used because it compiles to native instructions that can be +directly run by the processor and offers tight control over hardware (like C) +while offering high-level features such as generics, exceptions, and classes. +This combination of speed and functionality makes C++ +one of the most widely-used programming languages.  ```c++ -///////////////////////////////////////    -// C++ differences    -///////////////////////////////////////   +////////////////// +// Comparison to C +////////////////// + +// C++ is _almost_ a superset of C and shares its basic syntax for +// variable declarations, primitive types, and functions. +// However, C++ varies in some of the following ways: + +// A main() function in C++ should return an int, +// though void main() is accepted by most compilers (gcc, clang, etc.) +// 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) +{ +    // Command line arguments are passed in by argc and argv in the same way +    // they are in C. +    // argc indicates the number of arguments, +    // and argv is an array of C-style strings (char*) +    // representing the arguments. +    // The first argument is the name by which the program was called. +    // argc and argv can be omitted if you do not care about arguments, +    // giving the function signature of int main() + +    // An exit status of 0 indicates success. +    return 0; +} +// In C++, character literals are one byte. +sizeof('c') == 1 -//In C++    -//cannot use void main()    -int main() { //or int main(int argc, char **argv)    -    //cannot end with return;    -    return 0;    -    //Can also end without return statement    -}    -    -//In C++   -/*     -  //This could lead to compiler errors and is discouraged     -  //#if 0 #endif pairs are encouraged instead    -*/    -    -//In C++     -sizeof(10) //Typically 4    -sizeof('c') == 1     +// In C, character literals are the same size as ints. +sizeof('c') == sizeof(10) -//In C    -sizeof('c') == sizeof(10) //true chars are passed as ints    +// C++ has strict prototyping +void func(); // function which accepts no arguments -//In C++ strict prototyping    -void func(); //function which accepts no arguments    +// In C +void func(); // function which may accept any number of arguments -//In C    -void func(); //function which may accept arguments     - - -//In C++    -for(int i = 0; i < 10; i++) {;}    -//In C must int i must be declared before    +// Use nullptr instead of NULL in C++ +int* ip = nullptr; +// C standard headers are available in C++, +// but are prefixed with "c" and have no .h suffix. +#include <cstdio> -//C++ Supports Function overloading    -//Provided each function takes different    -//parameters     +int main() +{ +    printf("Hello, world!\n"); +    return 0; +} -void printing(char const *myString)     -{printf("String %s\n",myString);} //Hello    +/////////////////////// +// Function overloading +/////////////////////// -void printing(int myInt)     -{printf("My int is %d",myInt);} //15    +// C++ supports function overloading +// provided each function takes different parameters. -int main ()     -{    -    printing("Hello");    -    printing(15);    -}    -    +void print(char const* myString) +{ +    printf("String %s\n", myString); +} +void print(int myInt) +{ +    printf("My int is %d", myInt); +} -//C++ Default Function Arguments    -void two_ints(int a = 1, int b = 4);    +int main() +{ +    print("Hello"); // Resolves to void print(const char*) +    print(15); // Resolves to void print(int) +} -int main()    -{     -    two_ints();            // arguments:  1, 4    -    two_ints(20);          // arguments: 20, 4    -    two_ints(20, 5);       // arguments: 20, 5    -}    +///////////////////////////// +// Default function arguments +///////////////////////////// +// You can provide default arguments for a function +// if they are not provided by the caller. -//C++ added the nullptr which is different from 0    -int *ip = nullptr;      // OK    -int value = nullptr;    // error: value is no pointer   +void doSomethingWithInts(int a = 1, int b = 4) +{ +    // Do something with the ints here +} +int main() +{ +    doSomethingWithInts();      // a = 1,  b = 4 +    doSomethingWithInts(20);    // a = 20, b = 4 +    doSomethingWithInts(20, 5); // a = 20, b = 5 +} -///////////////////////////////////////    -// C++ Additions ontop of C     -///////////////////////////////////////    +// Default arguments must be at the end of the arguments list. +void invalidDeclaration(int a = 1, int b) // Error! +{ +} -///////////////////////////////////////    -// C++ Namespace    -///////////////////////////////////////    -//Namespaces allow you to define your own     -//functions and variables for use     +///////////// +// Namespaces +///////////// + +// Namespaces provide separate scopes for variable, function, +// and other declarations. +// Namespaces can be nested. + +namespace First { +    namespace Nested { +        void foo() +        { +            printf("This is First::Nested::foo\n"); +        } +    } // end namespace Nested +} // end namespace First + +namespace Second { +    void foo() +    { +        printf("This is Second::foo\n") +    } +} -// Use '::' to change variable (or function) scope    -// Putting '::' before a function or variable will    -// reference a global scope     +void foo() +{ +    printf("This is global foo\n"); +} -// This allows you to make normal c library calls    -// std is for standard library     -using namespace std;    +int main() +{ +    // Assume everything is from the namespace "Second" +    // unless otherwise specified. +    using namespace Second; -#include <stdio.h>     +    foo(); // prints "This is Second::foo" +    First::Nested::foo(); // prints "This is First::Nested::foo" +    ::foo(); // prints "This is global foo" +} -int counter = 50;                // global variable     +/////////////// +// Input/Output +/////////////// -int main()    -{    -    for (int counter = 1;        // this refers to the    -    counter < 2;                 // local variable    -    counter++)    -    {    -        printf("Global var %d local var %d\n",     -            ::counter,           // global variable     -            counter);            // local variable     -        // => Global var 50 local var 1    -    }    -}    +// C++ input and output uses streams +// cin, cout, and cerr represent stdin, stdout, and stderr. +// << is the insertion operator and >> is the extraction operator. -// Namespaces can be nested    +#include <iostream> // Include for I/O streams +using namespace std; // Streams are in the std namespace (standard library) -namespace myFirstNameSpace    -{    -    namespace myInnerSoul    -    {    -        cos(int x)    -        {    -            printf("My inner soul was made to program.");    -	}    -    }    -}    +int main() +{ +   int myInt; -namespace anotherNameSpace   -{    -    cos(int x) {;} //does nothing    -}    -    -int main()    -{    -    //Specify the full path because main is outside of both namespaces.     -    //Will print out My inner soul was made to program.     -    myFirstNameSpace::myInnerSoul::cos(60);    -}    +   // Prints to stdout (or terminal/screen) +   cout << "Enter your favorite number:\n"; +   // Takes in input +   cin >> myInt; +   // cout can also be formatted +   cout << "Your favorite number is " << myInt << "\n"; +   // prints "Your favorite number is <myInt>" -///////////////////////////////////////    -// C++ Strings    -///////////////////////////////////////    +    cerr << "Used for error messages"; +} -//Strings in C++ are Objects and have many functions   -myString = "Hello";    -myOtherString = " World";    +////////// +// Strings +////////// -myString + myOtherString; // => "Hello World"     +// Strings in C++ are objects and have many member functions +#include <string> -myString + ' You'; // => "Hello You"    +using namespace std; // Strings are also in the namespace std (standard library) -myString != myOtherString; //True    +string myString = "Hello"; +string myOtherString = " World"; -//An example of a string method    -myString.append(" Dog"); // => "Hello Dog"    +// + is used for concatenation. +cout << myString + myOtherString; // "Hello World" +cout << myString + " You"; // "Hello You" -///////////////////////////////////////    -// C++ Input Output    -///////////////////////////////////////    +// C++ strings are mutable and have value semantics. +myString.append(" Dog"); +cout << myString; // "Hello Dog" -//C++ input and output streams    -//cin, cout, cerr, << is insertion and >> is extraction operator    -#include <iostream>    -using namespace std;    +///////////// +// References +///////////// -int main()    -{    +// In addition to pointers like the ones in C, +// C++ has _references_. +// These are pointer types that cannot be reassigned once set +// and cannot be null. +// They also have the same syntax as the variable itself: +// No * is needed for dereferencing and +// & (address of) is not used for assignment. -   int myInt;    -     -   //Prints to stdout (or terminal/screen)    -   cout << "Enter your fav number:\n";    -   //Takes in input    -   cin >> myInt;    +using namespace std; -   //cout can also be formatted    -   cout << "Your fav number is " << myInt << "\n";    -   //Your fav number is ##   +string foo = "I am foo"; +string bar = "I am bar"; -   cerr << "Used for error messages";    -}    +string& fooRef = foo; // This creates a reference to foo. +fooRef += ". Hi!"; // Modifies foo through the reference +cout << fooRef; // Prints "I am foo. Hi!" -///////////////////////////////////////    -// C++ Classes    -/////////////////////////////////////// +fooRef = bar; // Error: references cannot be reassigned. +const string& barRef = bar; // Create a const reference to bar. +// Like C, const values (and pointers and references) cannot be modified. +barRef += ". Hi!"; // Error, const references cannot be modified. -//First example of classes    -#include <iostream>    +////////////////////////////////////////// +// Classes and object-oriented programming +////////////////////////////////////////// -//define a class     -class Doggie    -{    -    std::string name;    -    int         weight;    +// First example of classes +#include <iostream> -   // These are only the declarations    -   //Can also have private and protected    -   public:      -       //The public methods (can also include variables)    +// Declare a class. +// Classes are usually declared in header (.h or .hpp) files. +class Dog { +    // Member variables and functions are private by default. +    std::string name; +    int weight; -   // Default constructor    -   Doggie();    +// All members following this are public +// until "private:" or "protected:" is found. +public: -   void setName(std::string dogsName);    -   void setWeight(int dogsWeight);     -   void printDog();    +    // Default constructor +    Dog(); -   //Can define functions within class declaration too    -   void dogBark() {std::cout << "Bark Bark\n"}    +    // Member function declarations (implementations to follow) +    // Note that we use std::string here instead of placing +    // using namespace std; +    // above. +    // Never put a "using namespace" statement in a header. +    void setName(const std::string& dogsName); -   //Destructors are methods that free the allocated space    -   ~doggieDestructor();    -   //if no destructor compiler defines the trivial destructor    +    void setWeight(int dogsWeight); -//Classes are similar to structs and must close the } with ;     -};    +    // Functions that do not modify the state of the object +    // should be marked as const. +    // This allows you to call them if given a const reference to the object. +    // Also note the functions must be explicitly declared as _virtual_ +    // in order to be overridden in derived classes. +    // Functions are not virtual by default for performance reasons. +    virtual void print() const; -// This is the implementation of the class methods    -// Also called the definition    -void Doggie::Doggie () {    -    std::cout << "A doggie is born. Woof!\n";    -}    -  -void Doggie::setName (std::string doggie_name) {     -    name = doggie_name;    -}    +    // 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 Doggie::setWeight (int doggie_weight) {    -    weight = doggie_weight;    -}    +    // Along with constructors, C++ provides destructors. +    // These are called when an object is deleted or falls out of scope. +    // This enables powerful paradigms such as RAII +    // (see below) +    // Destructors must be virtual to allow classes to be derived from this one. +    virtual ~Dog(); -void Doggie::printDog () {    -    std::cout << "Dog is " << name << " weighs" << weight << "\n";     -}    +}; // A semicolon must follow the class definition. -void Doggie::~doggieDestructor () {    -    delete[] name;    -    delete weight;     -}    +// Class member functions are usually implemented in .cpp files. +void Dog::Dog() +{ +    std::cout << "A dog has been constructed\n"; +} -int main () {     -  Doggie deedee; // prints out a doggie is born. Woof!    -  deedee.setName ("Barkley");     -  deedee.setWeight(1000000);    -  deedee.printDog;    -  //prints => Dog is Barkley weighs 1000000     -  return 0;    -}    +// Objects (such as strings) should be passed by reference +// if you are modifying them or const reference if you are not. +void Dog::setName(const std::string& dogsName) +{ +    name = doggie_name; +} +void Dog::setWeight(int dogsWeight) +{ +    weight = dogsWeight; +} -//C++ Class inheritance    +// Notice that "virtual" is only needed in the declaration, not the definition. +void Dog::print() const +{ +    std::cout << "Dog is " << name << " and weighs " << weight << "kg\n"; +} -class German_Sheperd    +void Dog::~Dog()  { -   //This class now inherits everything public and protected from Doggie class    -   Doggie      d_dog;    - -   //Good practice to put d_ in front of datatypes in classes    -   std::string d_type;    - -   public:   -      void dogType() {d_type = "German Sheperd";}    -};    - - - -///////////////////////////////////////    -// C++ Exception Handling    -///////////////////////////////////////     - -try {    -   throw 12.25;  // throws a double no handler declared    -} catch (int errorNum)    -{    -  std::cout << "I caught an int " << errorNum << "\n";    -//default catcher    -} catch (...)    -{    -    std::cout << "I got an error. Not sure what but I can pass it up.";    -    throw;    -}    - - -///////////////////////////////////////     -// C++ Operator Overloading    -///////////////////////////////////////    - -// In C++ you can overload operators such as +, -, new, etc.    - -#include <iostream>    -using namespace std;    - -class Vector {    -    public:    -        double x,y;    -        Vector () {};    -        Vector (double a, double b) : x(a), y(b) {}    -        Vector operator + (const CVector&);    -        Vector operator += (const CVector&);    -};    -  -Vector Vector::operator+ (const Vector& rhs)     -{    -    Vector temp;    -    temp.x = x + rhs.x;    -    temp.y = y + rhs.y;    -    return temp;    -}    - -Vector Vector::operator+= (const Vector& rhs)    -{    -    x += rhs.x;    -    y += rhs.y;    -    return *this;    -}     - -int main () {    -    Vector up (0,1);    -    Vector right (1,0);    -    Vector result;     -    // This calls the Vector + operator    -    // Vector up calls the + (function) with right as its paramater    -    result = up + right;    -    // prints out => Result is upright (1,1)    -    cout << "Result is upright (" << result.x << ',' << result.y << ")\n";    -    return 0;    +    cout << "Goodbye " << name << "\n";  } +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" +    return 0; +} // prints "Goodbye Barkley" + +// Inheritance: + +// This class inherits everything public and protected from the Dog class +class OwnedDog : public Dog { + +    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 +    // for a more general introduction if you are unfamiliar with +    // subtype polymorphism. +    // The override keyword is optional but makes sure you are actually +    // overriding the method in a base class. +    void print() const override; + +private: +    std::string owner; +}; + +// Meanwhile, in the corresponding .cpp file: + +void OwnedDog::setOwner(const std::string& dogsOwner) +{ +    owner = dogsOwner; +} + +void OwnedDog::print() const +{ +    Dog::print(); // Call the print function in the base Dog class +    std::cout << "Dog is owned by " << owner << "\n"; +    // Prints "Dog is <name> and weights <weight>" +    //        "Dog is owned by <owner>" +} + +////////////////////////////////////////// +// Initialization and Operator Overloading +////////////////////////////////////////// + +// In C++ you can overload the behavior of operators such as +, -, *, /, etc. +// This is done by defining a function which is called +// whenever the operator is used. + +#include <iostream> +using namespace std; + +class Point { +public: +    // Member variables can be given default values in this manner. +    double x = 0; +    double y = 0; + +    // Define a default constructor which does nothing +    // but initialize the Point to the default value (0, 0) +    Point() { }; + +    // The following syntax is known as an initialization list +    // and is the proper way to initialize class member values +    Point (double a, double b) : +        x(a), +        y(b) +    { /* Do nothing except initialize the values */ } + +    // Overload the + operator. +    Point operator+(const Point& rhs) const; + +    // Overload the += operator +    Point& operator+=(const Point& rhs); + +    // It would also make sense to add the - and -= operators, +    // but we will skip those for brevity. +}; + +Point Point::operator+(const Point& rhs) const +{ +    // Create a new point that is the sum of this one and rhs. +    return Point(x + rhs.x, y + rhs.y); +} + +Point& Point::operator+=(const Point& rhs) +{ +    x += rhs.x; +    y += rhs.y; +    return *this; +} + +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 result = up + right; +    // Prints "Result is upright (1,1)" +    cout << "Result is upright (" << result.x << ',' << result.y << ")\n"; +    return 0; +} + +///////////////////// +// Exception Handling +///////////////////// + +// The standard library provides a few exception types +// (see http://en.cppreference.com/w/cpp/error/exception) +// but any type can be thrown an as exception +#include <exception> + +// 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"); +} +// Catch exceptions by const reference if they are objects +catch (const std::exception& ex) +{ +  std::cout << ex.what(); +// Catches any exception not caught by previous _catch_ blocks +} catch (...) +{ +    std::cout << "Unknown exception caught"; +    throw; // Re-throws the exception +} + +/////// +// RAII +/////// + +// RAII stands for Resource Allocation Is Initialization. +// It is often considered the most powerful paradigm in C++, +// and is the simple concept that a constructor for an object +// acquires that object's resources and the destructor releases them. + +// To understand how this is useful, +// consider a function that uses a C file handle: +void doSomethingWithAFile(const char* filename) +{ +    // To begin with, assume nothing can fail. + +    FILE* fh = fopen(filename, "r"); // Open the file in read mode. + +    doSomethingWithTheFile(fh); +    doSomethingElseWithIt(fh); + +    fclose(fh); // Close the file handle. +} + +// Unfortunately, things are quickly complicated by error handling. +// Suppose fopen can fail, and that doSomethingWithTheFile and +// doSomethingElseWithIt return error codes if they fail. +// (Exceptions are the preferred way of handling failure, +//  but some programmers, especially those with a C background, +//  disagree on the utility of exceptions). +// We now have to check each call for failure and close the file handle +// if a problem occurred. +bool doSomethingWithAFile(const char* filename) +{ +    FILE* fh = fopen(filename, "r"); // Open the file in read mode +    if (fh == nullptr) // The returned pointer is null on failure. +        reuturn false; // Report that failure to the caller. + +    // Assume each function returns false if it failed +    if (!doSomethingWithTheFile(fh)) { +        fclose(fh); // Close the file handle so it doesn't leak. +        return false; // Propagate the error. +    } +    if (!doSomethingElseWithIt(fh)) { +        fclose(fh); // Close the file handle so it doesn't leak. +        return false; // Propagate the error. +    } + +    fclose(fh); // Close the file handle so it doesn't leak. +    return true; // Indicate success +} + +// C programmers often clean this up a little bit using goto: +bool doSomethingWithAFile(const char* filename) +{ +    FILE* fh = fopen(filename, "r"); +    if (fh == nullptr) +        reuturn false; + +    if (!doSomethingWithTheFile(fh)) +        goto failure; + +    if (!doSomethingElseWithIt(fh)) +        goto failure; + +    fclose(fh); // Close the file +    return true; // Indicate success + +failure: +    fclose(fh); +    return false; // Propagate the error +} + +// If the functions indicate errors using exceptions, +// things are a little cleaner, but still sub-optimal. +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."); + +    try { +        doSomethingWithTheFile(fh); +        doSomethingElseWithIt(fh); +    } +    catch (...) { +        fclose(fh); // Be sure to close the file if an error occurs. +        throw; // Then re-throw the exception. +    } + +    fclose(fh); // Close the file +    // Everything succeeded +} + +// Compare this to the use of C++'s file stream class (fstream) +// fstream uses its destructor to close the file. +// Recall from above that destructors are automatically called +// whenver an object falls out of scope. +void doSomethingWithAFile(const std::string& filename) +{ +    // ifstream is short for input file stream +    std::ifstream fh(filename); // Open the file + +    // Do things with the file +    doSomethingWithTheFile(fh); +    doSomethingElseWithIt(fh); + +} // The file is automatically closed here by the destructor + +// This has _massive_ advantages: +// 1. No matter what happens, +//    the resource (in this case the file handle) will be cleaned up. +//    Once you write the destructor correctly, +//    It is _impossible_ to forget to close the handle and leak the resource. +// 2. Note that the code is much cleaner. +//    The destructor handles closing the file behind the scenes +//    without you having to worry about it. +// 3. The code is exception safe. +//    An exception can be thrown anywhere in the function and cleanup +//    will still occur. + +// All idiomatic C++ code uses RAII extensively for all resources. +// Additional examples include +// - Memory using unique_ptr and shared_ptr +// - Containers - the standard library linked list, +//   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  ``` -Futher Reading    +Futher Reading: + +An up-to-date language reference can be found at +<http://cppreference.com/w/cpp> -for more resources see: http://www.icce.rug.nl/documents/cplusplus/    -for other reference material: http://www.cplusplus.com/doc/tutorial/   +Additional resources may be found at <http://cplusplus.com>  | 
