diff options
Diffstat (limited to 'c++.html.markdown')
-rw-r--r-- | c++.html.markdown | 590 |
1 files changed, 590 insertions, 0 deletions
diff --git a/c++.html.markdown b/c++.html.markdown new file mode 100644 index 00000000..9f357b08 --- /dev/null +++ b/c++.html.markdown @@ -0,0 +1,590 @@ +--- +language: c++ +filename: learncpp.cpp +contributors: + - ["Steven Basart", "http://github.com/xksteven"] + - ["Matt Kline", "https://github.com/mrkline"] +lang: en +--- + +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++ +////////////////// +// 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, character literals are the same size as ints. +sizeof('c') == sizeof(10) + + +// C++ has strict prototyping +void func(); // function which accepts no arguments + +// In C +void func(); // function which may accept any number of arguments + +// 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> + +int main() +{ + printf("Hello, world!\n"); + return 0; +} + +/////////////////////// +// Function overloading +/////////////////////// + +// C++ supports function overloading +// provided each function takes different parameters. + +void print(char const* myString) +{ + printf("String %s\n", myString); +} + +void print(int myInt) +{ + printf("My int is %d", myInt); +} + +int main() +{ + print("Hello"); // Resolves to void print(const char*) + print(15); // Resolves to void print(int) +} + +///////////////////////////// +// Default function arguments +///////////////////////////// + +// You can provide default arguments for a function +// if they are not provided by the caller. + +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 +} + +// Default arguments must be at the end of the arguments list. + +void invalidDeclaration(int a = 1, int b) // Error! +{ +} + + +///////////// +// 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") + } +} + +void foo() +{ + printf("This is global foo\n"); +} + +int main() +{ + // Assume everything is from the namespace "Second" + // unless otherwise specified. + using namespace Second; + + foo(); // prints "This is Second::foo" + First::Nested::foo(); // prints "This is First::Nested::foo" + ::foo(); // prints "This is global foo" +} + +/////////////// +// Input/Output +/////////////// + +// C++ input and output uses streams +// cin, cout, and cerr represent stdin, stdout, and stderr. +// << is the insertion operator and >> is the extraction operator. + +#include <iostream> // Include for I/O streams + +using namespace std; // Streams are in the std namespace (standard library) + +int main() +{ + int myInt; + + // 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>" + + cerr << "Used for error messages"; +} + +////////// +// Strings +////////// + +// Strings in C++ are objects and have many member functions +#include <string> + +using namespace std; // Strings are also in the namespace std (standard library) + +string myString = "Hello"; +string myOtherString = " World"; + +// + is used for concatenation. +cout << myString + myOtherString; // "Hello World" + +cout << myString + " You"; // "Hello You" + +// C++ strings are mutable and have value semantics. +myString.append(" Dog"); +cout << myString; // "Hello Dog" + + +///////////// +// References +///////////// + +// 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. + +using namespace std; + +string foo = "I am foo"; +string bar = "I am bar"; + + +string& fooRef = foo; // This creates a reference to foo. +fooRef += ". Hi!"; // Modifies foo through the reference +cout << fooRef; // Prints "I am foo. Hi!" + +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. + +////////////////////////////////////////// +// Classes and object-oriented programming +////////////////////////////////////////// + +// First example of classes +#include <iostream> + +// 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; + +// All members following this are public +// until "private:" or "protected:" is found. +public: + + // Default constructor + Dog(); + + // 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); + + void setWeight(int dogsWeight); + + // 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; + + // Functions can also be defined inside the class body. + // Functions defined as such are automatically inlined. + 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. + // This enables powerful paradigms such as RAII + // (see below) + // Destructors must be virtual to allow classes to be derived from this one. + virtual ~Dog(); + +}; // A semicolon must follow the class definition. + +// Class member functions are usually implemented in .cpp files. +void Dog::Dog() +{ + std::cout << "A dog has been constructed\n"; +} + +// 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 = dogsName; +} + +void Dog::setWeight(int dogsWeight) +{ + weight = dogsWeight; +} + +// 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"; +} + +void Dog::~Dog() +{ + 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: + +An up-to-date language reference can be found at +<http://cppreference.com/w/cpp> + +Additional resources may be found at <http://cplusplus.com> |