|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
转自 http://learnxinyminutes.com/docs/c++/
源文件下载
learncpp.zip
(5.39 KB, 下载次数: 29)
- //////////////////
- // 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
复制代码
|
|