From 5a1ccececa4ae0211aba96cea5709267678e73e6 Mon Sep 17 00:00:00 2001 From: Bohdan Shtepan Date: Thu, 3 Dec 2015 17:19:34 +0200 Subject: Adds c++-ru --- ru-ru/c++-ru.html.markdown | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 ru-ru/c++-ru.html.markdown diff --git a/ru-ru/c++-ru.html.markdown b/ru-ru/c++-ru.html.markdown new file mode 100644 index 00000000..9e62ee0c --- /dev/null +++ b/ru-ru/c++-ru.html.markdown @@ -0,0 +1,12 @@ +--- +language: c++ +filename: learncpp-ru.cpp +contributors: + - ["Steven Basart", "http://github.com/xksteven"] + - ["Matt Kline", "https://github.com/mrkline"] + - ["Geoff Liu", "http://geoffliu.me"] + - ["Connor Waters", "http://github.com/connorwaters"] +translators: + - ["Bohdan Shtepan", "http://modern-dev.com"] +lang: ru-ru +--- \ No newline at end of file -- cgit v1.2.3 From 9e7bd0263972b588ebe41ee6382a86b06d6bd4db Mon Sep 17 00:00:00 2001 From: Bohdan Shtepan Date: Thu, 3 Dec 2015 19:41:19 +0200 Subject: Starts translation --- ru-ru/c++-ru.html.markdown | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/ru-ru/c++-ru.html.markdown b/ru-ru/c++-ru.html.markdown index 9e62ee0c..c1c5599b 100644 --- a/ru-ru/c++-ru.html.markdown +++ b/ru-ru/c++-ru.html.markdown @@ -9,4 +9,13 @@ contributors: translators: - ["Bohdan Shtepan", "http://modern-dev.com"] lang: ru-ru ---- \ No newline at end of file +--- + +C++ - компилируемый, статически типизированный язык программирования общего назначения, который, +[как заявляет создатель языка Бьёрн Страуструп](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Keynote), +был разработан как + +- "лучшая замена C" +- язык с поддержкой абстракции данных +- язык с поддержкой объектно-ориентированого программирования +- язык с поддержкой обобщенного программирования \ No newline at end of file -- cgit v1.2.3 From 5cf95634321084fd104df23fa5a9fbb6167fbc21 Mon Sep 17 00:00:00 2001 From: Bohdan Shtepan Date: Thu, 3 Dec 2015 20:11:29 +0200 Subject: Language overview --- ru-ru/c++-ru.html.markdown | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ru-ru/c++-ru.html.markdown b/ru-ru/c++-ru.html.markdown index c1c5599b..7fb8b9da 100644 --- a/ru-ru/c++-ru.html.markdown +++ b/ru-ru/c++-ru.html.markdown @@ -6,6 +6,7 @@ contributors: - ["Matt Kline", "https://github.com/mrkline"] - ["Geoff Liu", "http://geoffliu.me"] - ["Connor Waters", "http://github.com/connorwaters"] + - ["Bohdan Shtepan", "http://modern-dev.com"] translators: - ["Bohdan Shtepan", "http://modern-dev.com"] lang: ru-ru @@ -18,4 +19,10 @@ C++ - компилируемый, статически типизированн - "лучшая замена C" - язык с поддержкой абстракции данных - язык с поддержкой объектно-ориентированого программирования -- язык с поддержкой обобщенного программирования \ No newline at end of file +- язык с поддержкой обобщенного программирования + +Хотя его синтаксис может показаться более трудным или сложным для понимания, чем в более современных языках, +он широко применяется т.к. код написанный на C++ компилируется в набор инструкций, которые могут быть выполнены напрямую +процессором. C++ широко используется для разработки программного обеспечения, являясь одним из самых популярных языков +программирования. Область его применения включает создание операционных систем, разнообразных прикладных программ, драйверов +устройств, приложений для встраиваемых систем, высокопроизводительных серверов, а также развлекательных приложений (игр). \ No newline at end of file -- cgit v1.2.3 From 83f3d7dc3bacab40bdee1c545fa92edb17777bf2 Mon Sep 17 00:00:00 2001 From: Bohdan Shtepan Date: Sat, 5 Dec 2015 04:23:07 +0200 Subject: Translated "Comparision to C", "Function overloading", "Default arguments" and "Namespaces" sections --- ru-ru/c++-ru.html.markdown | 873 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 871 insertions(+), 2 deletions(-) diff --git a/ru-ru/c++-ru.html.markdown b/ru-ru/c++-ru.html.markdown index 7fb8b9da..99798bbb 100644 --- a/ru-ru/c++-ru.html.markdown +++ b/ru-ru/c++-ru.html.markdown @@ -6,7 +6,6 @@ contributors: - ["Matt Kline", "https://github.com/mrkline"] - ["Geoff Liu", "http://geoffliu.me"] - ["Connor Waters", "http://github.com/connorwaters"] - - ["Bohdan Shtepan", "http://modern-dev.com"] translators: - ["Bohdan Shtepan", "http://modern-dev.com"] lang: ru-ru @@ -25,4 +24,874 @@ C++ - компилируемый, статически типизированн он широко применяется т.к. код написанный на C++ компилируется в набор инструкций, которые могут быть выполнены напрямую процессором. C++ широко используется для разработки программного обеспечения, являясь одним из самых популярных языков программирования. Область его применения включает создание операционных систем, разнообразных прикладных программ, драйверов -устройств, приложений для встраиваемых систем, высокопроизводительных серверов, а также развлекательных приложений (игр). \ No newline at end of file +устройств, приложений для встраиваемых систем, высокопроизводительных серверов, а также развлекательных приложений (игр). + +```c++ +////////////////// +// Сравнение с C +////////////////// + +// C++ практически представляет собой надмножество C и имеет схожий синтаксис +// для объявления переменных, примитивов и функций. + +// Также как и в С, точкой входа в программу является функция с именем main, +// которая возвращает целочисленное значение. +// Это значение является кодом ответа программы. +// Смотрите https://goo.gl/JYGKyv для более подробной информации. +int main(int argc, char** argv) +{ + // Аргументы командной строки переданные в программу хранятся в переменных + // argc и argv, также как и в C. + // argc указывает на количество аргументов, + // а argv является масивом C-подобных строк (char*), который непосредсвенно + // содержит аргументы. + // Первым аргументом всегда передается имя программы. + // argc и argv могут быть опущены если вы не планируете работать с аругментамы + // коммандной строки. + // Тогда сигнатура функции будет иметь следующий вид int main() + + // Возвращаемое значение 0 указывает на успешное завершение программы. + return 0; +} + +// Тем не менее, C++ имеет свои отличия: + +// В C++, символьные литералы являются символами. +sizeof('c') == sizeof(char) == 1 + +// В С, символьные литералы - целые числа. +sizeof('c') == sizeof(int) + + +// C++ имеет строго прототипирование. +void func(); // функция, которая не принимает аргументов. + +// In C +void func(); // функция, которая может принять сколько угодно аргументов. + +// Использование nullptr вместо NULL в C++. +int* ip = nullptr; + +// Стандартные заголовочные файлы С доступны в С++, +// но с префиксом "с" и не имеют суффикса .h. +#include + +int main() +{ + printf("Hello, world!\n"); + return 0; +} + +/////////////////////// +// Перегрузка функций +/////////////////////// + +// С++ поддерживает перегрузку функций, при условии, +// что каждая функция принимает различные параметры. + +void print(char const* myString) +{ + printf("String %s\n", myString); +} + +void print(int myInt) +{ + printf("My int is %d", myInt); +} + +int main() +{ + print("Hello"); // Использование void print(const char*) + print(15); // Использование void print(int) +} + +///////////////////////////// +// Аргументы функций по умолчанию +///////////////////////////// + +// Вы можете предоставить аргументы по умолчанию для функции, +// если они не предоставлены при вызове функции. + +void doSomethingWithInts(int a = 1, int b = 4) +{ + // Здесь что-то делаем с числами +} + +int main() +{ + doSomethingWithInts(); // a = 1, b = 4 + doSomethingWithInts(20); // a = 20, b = 4 + doSomethingWithInts(20, 5); // a = 20, b = 5 +} + +// Аргументы по умолчанию должен быть в конце списка аргументов. + +void invalidDeclaration(int a = 1, int b) // Ошибка! +{ +} + + +///////////// +// Пространства имен +///////////// + +// Пространства имен предоставляют отдельные области для переменной, +// функции и других объявлений. +// Пространства имен могут быть вложенными. + +namespace First { + namespace Nested { + void foo() + { + printf("This is First::Nested::foo\n"); + } + } // конец пространства имен Nested +} // конец пространства имен First + +namespace Second { + void foo() + { + printf("This is Second::foo\n") + } +} + +void foo() +{ + printf("This is global foo\n"); +} + +int main() +{ + // Включает все функци с пространства имен Second в текущую область видиомти. + // Обратите внимание, что простой вызов foo() больше не работает, + // так как теперь не ясно вызываем ли мы foo с пространства имен Second или + // из глобальной области видимости. + using namespace Second; + + Second::foo(); // напечатает "This is Second::foo" + First::Nested::foo(); // напечатает "This is First::Nested::foo" + ::foo(); // напечатает "This is global foo" +} + +/////////////// +// Ввод/Вывод +/////////////// + +// 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 // 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 " + + cerr << "Used for error messages"; +} + +////////// +// Строки +////////// + +// Strings in C++ are objects and have many member functions +#include + +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!" + +// Doesn't reassign "fooRef". This is the same as "foo = bar", and +// foo == "I am bar" +// after this line. +cout << &fooRef << endl; //Prints the address of foo +fooRef = bar; +cout << &fooRef << endl; //Still prints the address of foo +cout << fooRef; // Prints "I am bar" + +//The address of fooRef remains the same, i.e. it is still referring to foo. + + +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. + +// Sidetrack: Before we talk more about references, we must introduce a concept +// called a temporary object. Suppose we have the following code: +string tempObjectFun() { ... } +string retVal = tempObjectFun(); + +// What happens in the second line is actually: +// - a string object is returned from tempObjectFun +// - a new string is constructed with the returned object as argument to the +// constructor +// - the returned object is destroyed +// The returned object is called a temporary object. Temporary objects are +// created whenever a function returns an object, and they are destroyed at the +// end of the evaluation of the enclosing expression (Well, this is what the +// standard says, but compilers are allowed to change this behavior. Look up +// "return value optimization" if you're into this kind of details). So in this +// code: +foo(bar(tempObjectFun())) + +// assuming foo and bar exist, the object returned from tempObjectFun is +// passed to bar, and it is destroyed before foo is called. + +// Now back to references. The exception to the "at the end of the enclosing +// expression" rule is if a temporary object is bound to a const reference, in +// which case its life gets extended to the current scope: + +void constReferenceTempObjectFun() { + // constRef gets the temporary object, and it is valid until the end of this + // function. + const string& constRef = tempObjectFun(); + ... +} + +// Another kind of reference introduced in C++11 is specifically for temporary +// objects. You cannot have a variable of its type, but it takes precedence in +// overload resolution: + +void someFun(string& s) { ... } // Regular reference +void someFun(string&& s) { ... } // Reference to temporary object + +string foo; +someFun(foo); // Calls the version with regular reference +someFun(tempObjectFun()); // Calls the version with temporary reference + +// For example, you will see these two versions of constructors for +// std::basic_string: +basic_string(const basic_string& other); +basic_string(basic_string&& other); + +// Idea being if we are constructing a new string from a temporary object (which +// is going to be destroyed soon anyway), we can have a more efficient +// constructor that "salvages" parts of that temporary string. You will see this +// concept referred to as "move semantics". + +///////////////////// +// Enums +///////////////////// + +// Enums are a way to assign a value to a constant most commonly used for +// easier visualization and reading of code +enum ECarTypes +{ + Sedan, + Hatchback, + SUV, + Wagon +}; + +ECarTypes GetPreferredCarType() +{ + return ECarTypes::Hatchback; +} + +// As of C++11 there is an easy way to assign a type to the enum which can be +// useful in serialization of data and converting enums back-and-forth between +// the desired type and their respective constants +enum ECarTypes : uint8_t +{ + Sedan, // 0 + Hatchback, // 1 + SUV = 254, // 254 + Hybrid // 255 +}; + +void WriteByteToFile(uint8_t InputValue) +{ + // Serialize the InputValue to a file +} + +void WritePreferredCarTypeToFile(ECarTypes InputCarType) +{ + // The enum is implicitly converted to a uint8_t due to its declared enum type + WriteByteToFile(InputCarType); +} + +// On the other hand you may not want enums to be accidentally cast to an integer +// type or to other enums so it is instead possible to create an enum class which +// won't be implicitly converted +enum class ECarTypes : uint8_t +{ + Sedan, // 0 + Hatchback, // 1 + SUV = 254, // 254 + Hybrid // 255 +}; + +void WriteByteToFile(uint8_t InputValue) +{ + // Serialize the InputValue to a file +} + +void WritePreferredCarTypeToFile(ECarTypes InputCarType) +{ + // Won't compile even though ECarTypes is a uint8_t due to the enum + // being declared as an "enum class"! + WriteByteToFile(InputCarType); +} + +////////////////////////////////////////// +// Classes and object-oriented programming +////////////////////////////////////////// + +// First example of classes +#include + +// 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) + // The destructor should be virtual if a class is to be derived from; + // if it is not virtual, then the derived class' destructor will + // not be called if the object is destroyed through a base-class reference + // or pointer. + virtual ~Dog(); + +}; // A semicolon must follow the class definition. + +// Class member functions are usually implemented in .cpp files. +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"; +} + +Dog::~Dog() +{ + cout << "Goodbye " << name << "\n"; +} + +int main() { + Dog myDog; // prints "A dog has been constructed" + myDog.setName("Barkley"); + myDog.setWeight(10); + myDog.print(); // 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 +// as well as private but may not directly access private members/methods +// without a public or protected method for doing so +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 and weights " + // "Dog is owned by " +} + +////////////////////////////////////////// +// 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 +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 parameter + Point result = up + right; + // Prints "Result is upright (1,1)" + cout << "Result is upright (" << result.x << ',' << result.y << ")\n"; + return 0; +} + +///////////////////// +// Templates +///////////////////// + +// Templates in C++ are mostly used for generic programming, though they are +// much more powerful than generic constructs in other languages. They also +// support explicit and partial specialization and functional-style type +// classes; in fact, they are a Turing-complete functional language embedded +// in C++! + +// 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 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, 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 intBox; + +// and you can use it as you would expect: +intBox.insert(123); + +// You can, of course, nest templates: +Box > boxOfBox; +boxOfBox.insert(intBox); + +// Until C++11, you had to place a space between the two '>'s, otherwise '>>' +// would be parsed as the right shift operator. + +// You will sometimes see +// template +// instead. The 'class' keyword and 'typename' keywords are _mostly_ +// interchangeable in this case. For the full explanation, see +// http://en.wikipedia.org/wiki/Typename +// (yes, that keyword has its own Wikipedia page). + +// Similarly, a template function: +template +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 +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 +///////////////////// + +// 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 +#include + +// 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::runtime_error("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 Acquisition 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. + return 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) + return 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::runtime_error("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 +// whenever 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 + +// containers with object keys of non-primitive values (custom classes) require +// compare function in the object itself or as a function pointer. Primitives +// have default comparators, but you can override it. +class Foo { +public: + int j; + Foo(int a) : j(a) {} +}; +struct compareFunction { + bool operator()(const Foo& a, const Foo& b) const { + return a.j < b.j; + } +}; +//this isn't allowed (although it can vary depending on compiler) +//std::map fooMap; +std::map fooMap; +fooMap[Foo(1)] = 1; +fooMap.find(Foo(1)); //true + +///////////////////// +// 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. + +// There is an exception made for bools. +// This is to allow you to test for null pointers with if(!ptr), +// but as a consequence you can assign nullptr to a bool directly! +*pt = nullptr; // This still compiles, even though '*pt' is a bool! + + +// '=' != '=' != '='! +// Calls Foo::Foo(const Foo&) or some variant (see move semantics) 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; + + +// How to truly clear a container: +class Foo { ... }; +vector v; +for (int i = 0; i < 10; ++i) + v.push_back(Foo()); + +// Following line sets size of v to 0, but destructors don't get called +// and resources aren't released! +v.empty(); +v.push_back(Foo()); // New value is copied into the first Foo we inserted + +// Truly destroys all values in v. See section about temporary objects for +// explanation of why this works. +v.swap(vector()); + +``` +Further Reading: + +An up-to-date language reference can be found at + + +Additional resources may be found at -- cgit v1.2.3 From aad2d2b6f2e44f7647d0512dea263029c1d4d1fa Mon Sep 17 00:00:00 2001 From: Bohdan Shtepan Date: Sat, 5 Dec 2015 16:07:14 +0200 Subject: Adds complete translation --- ru-ru/c++-ru.html.markdown | 582 ++++++++++++++++++++++----------------------- 1 file changed, 289 insertions(+), 293 deletions(-) diff --git a/ru-ru/c++-ru.html.markdown b/ru-ru/c++-ru.html.markdown index 99798bbb..5137ec1f 100644 --- a/ru-ru/c++-ru.html.markdown +++ b/ru-ru/c++-ru.html.markdown @@ -162,7 +162,7 @@ void foo() int main() { - // Включает все функци с пространства имен Second в текущую область видиомти. + // Включает все функци с пространства имен Second в текущую область видимости. // Обратите внимание, что простой вызов foo() больше не работает, // так как теперь не ясно вызываем ли мы foo с пространства имен Second или // из глобальной области видимости. @@ -177,26 +177,26 @@ int main() // Ввод/Вывод /////////////// -// C++ input and output uses streams -// cin, cout, and cerr represent stdin, stdout, and stderr. -// << is the insertion operator and >> is the extraction operator. +// Вводи и вывод в C++ использует потоки +// cin, cout и cerr предоставлнеы методами stdin, stdout и stderr. +// << - оператор вставки, >> - оператор извлечения. -#include // Include for I/O streams +#include // Включение файла для работы с потоками Ввода\Вывода. -using namespace std; // Streams are in the std namespace (standard library) +using namespace std; // Потоки доступны в пространстве имен std (стандартная библиотека) int main() { int myInt; - // Prints to stdout (or terminal/screen) + // Выводит stdout (или терминал\экран) cout << "Enter your favorite number:\n"; - // Takes in input + // Принимает ввод cin >> myInt; - // cout can also be formatted + // cout может принимать форматирование cout << "Your favorite number is " << myInt << "\n"; - // prints "Your favorite number is " + // напечатает "Your favorite number is " cerr << "Used for error messages"; } @@ -205,35 +205,35 @@ int main() // Строки ////////// -// Strings in C++ are objects and have many member functions +// Строки в C++ являются объектами и имеют много функций-членов. #include -using namespace std; // Strings are also in the namespace std (standard library) +using namespace std; // Строки также доступны в пространстве имен std (стандартная библиотек) 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. +// Строки в C++ могут изменяться и имеют семантику значений. 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. +// В добавок к указателям доступных в C, +// C++ имеет _ссылки_. +// Это такой тип указателя, который не может быть переназначен после инициализации +// и не может иметь значения null. +// Ссылки имеют схожий с переменными синтаксис: +// * больше не используется для разыменования и +// & (адрес) не используется для назначения. using namespace std; @@ -241,84 +241,80 @@ 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!" +string& fooRef = foo; // Здесь создается указатель на foo. +fooRef += ". Hi!"; // Изменяет foo по ссылке +cout << fooRef; // Печатает "I am foo. Hi!" -// Doesn't reassign "fooRef". This is the same as "foo = bar", and +// Не переназначает "fooRef". Это тоже самое как "foo = bar", и // foo == "I am bar" -// after this line. -cout << &fooRef << endl; //Prints the address of foo +// после этой строчки. +cout << &fooRef << endl; // Печатает адрес foo fooRef = bar; -cout << &fooRef << endl; //Still prints the address of foo -cout << fooRef; // Prints "I am bar" +cout << &fooRef << endl; // По-прежнему печатает адрес foo +cout << fooRef; // Печатает "I am bar" -//The address of fooRef remains the same, i.e. it is still referring to foo. +// Адрес fooRef остается тем же, то есть он по-прежнему ссылается на foo. -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. +const string& barRef = bar; // Создает const со ссылкой на bar. +// Также как и C, значения const (и указателей и ссылок) не могут быть изменены. +barRef += ". Hi!"; // Ошибка, указатель const не может быть изменен. -// Sidetrack: Before we talk more about references, we must introduce a concept -// called a temporary object. Suppose we have the following code: +// Обходной путь: Прежде чем мы рассмотрим указатели более детально, нам нужно ознакомится +// с концепцией известной как "временный объект". Представьте, что мы имеем следующий код string tempObjectFun() { ... } string retVal = tempObjectFun(); -// What happens in the second line is actually: -// - a string object is returned from tempObjectFun -// - a new string is constructed with the returned object as argument to the -// constructor -// - the returned object is destroyed -// The returned object is called a temporary object. Temporary objects are -// created whenever a function returns an object, and they are destroyed at the -// end of the evaluation of the enclosing expression (Well, this is what the -// standard says, but compilers are allowed to change this behavior. Look up -// "return value optimization" if you're into this kind of details). So in this -// code: +// Вот что на самом деле происходит во второй строе: +// - tempObjectFun возвращает строковый объект +// - с возвращаемого объекта создается новая строка в качестве аргумента конструктору +// - возвращаемый объект уничтожается +// Возвращаемый объект называется временным объектом. Временные объекты создаются +// когда функция возвращает объект, и уничтожаются в конце выполнения обрамляющего +// выражения (По крайней мере, так это описывает спецификация, хотя компиляторы могут +// изменять это поведение. Для более подробной информации смотрите "оптимизация +// возвращаемого значения". Таким образом в этом коде: foo(bar(tempObjectFun())) -// assuming foo and bar exist, the object returned from tempObjectFun is -// passed to bar, and it is destroyed before foo is called. +// предполагая, что foo и bar существуют, объект возвращаемый tempObjectFun передается +// в bar, и уничтожается перед вызовом foo. -// Now back to references. The exception to the "at the end of the enclosing -// expression" rule is if a temporary object is bound to a const reference, in -// which case its life gets extended to the current scope: +// Возвращаемся к указателям. Исключением для правила "в конце выполнения обрамляющего +// выражения" является временный объект привязанный к ссылке const, в этом случае +// его жизненный цикл продлевается до текущей области видимости: void constReferenceTempObjectFun() { - // constRef gets the temporary object, and it is valid until the end of this - // function. + // constRef получает временный объект, и он действителен до конца этой функции. const string& constRef = tempObjectFun(); ... } -// Another kind of reference introduced in C++11 is specifically for temporary -// objects. You cannot have a variable of its type, but it takes precedence in -// overload resolution: +// В C++11 предоставлен еще один тип ссылок специально для временных объектов. +// objects. Вы не можете объявить переменную этого типа, но он имеет приоритет в +// в резолюции перегрузки: -void someFun(string& s) { ... } // Regular reference -void someFun(string&& s) { ... } // Reference to temporary object +void someFun(string& s) { ... } // Обычная ссылка +void someFun(string&& s) { ... } // Ссылка на временный объект string foo; -someFun(foo); // Calls the version with regular reference -someFun(tempObjectFun()); // Calls the version with temporary reference +someFun(foo); // Выполняет версию с обычной ссылкой +someFun(tempObjectFun()); // Выполняет версию с временной ссылкой. -// For example, you will see these two versions of constructors for -// std::basic_string: +// Например, существуют следующие две версии конструктора std::basic_string: basic_string(const basic_string& other); basic_string(basic_string&& other); -// Idea being if we are constructing a new string from a temporary object (which -// is going to be destroyed soon anyway), we can have a more efficient -// constructor that "salvages" parts of that temporary string. You will see this -// concept referred to as "move semantics". +// Идея в том, если мы конструируем новую строку из временного объекта (который +// так или иначе будет уничтожен), мы можем использовать более эффективный конструктор, +// который "спасает" части этой временной строки. Эта концепция была названа +// "move semantics". ///////////////////// -// Enums +// Перечисления ///////////////////// -// Enums are a way to assign a value to a constant most commonly used for -// easier visualization and reading of code +// Перечисления - способ объявления констант и установки их значений в основном +// использующийся для упрощения чтения кода. enum ECarTypes { Sedan, @@ -332,9 +328,9 @@ ECarTypes GetPreferredCarType() return ECarTypes::Hatchback; } -// As of C++11 there is an easy way to assign a type to the enum which can be -// useful in serialization of data and converting enums back-and-forth between -// the desired type and their respective constants +// На момент выхода C++11 есть простой способ назначения типа перечисления, что +// полезно в случае сериализации данных и преобразований между конечным типом и +// соответствующими константами. enum ECarTypes : uint8_t { Sedan, // 0 @@ -345,18 +341,19 @@ enum ECarTypes : uint8_t void WriteByteToFile(uint8_t InputValue) { - // Serialize the InputValue to a file + // Сериализуем InputValue в файл } void WritePreferredCarTypeToFile(ECarTypes InputCarType) { - // The enum is implicitly converted to a uint8_t due to its declared enum type + // Перечисление неявно преобразуется в uint8_t из-за раннее объявленного + // типа перечисления. WriteByteToFile(InputCarType); } -// On the other hand you may not want enums to be accidentally cast to an integer -// type or to other enums so it is instead possible to create an enum class which -// won't be implicitly converted +// С другой стороны, чтобы избежать случайного приведения к целочисленному типу или +// другому перечислению, вы можете создать класс перечисления, который не будет +// преобразовываться неявно. enum class ECarTypes : uint8_t { Sedan, // 0 @@ -367,78 +364,78 @@ enum class ECarTypes : uint8_t void WriteByteToFile(uint8_t InputValue) { - // Serialize the InputValue to a file + // Сериализуем InputValue в файл } void WritePreferredCarTypeToFile(ECarTypes InputCarType) { - // Won't compile even though ECarTypes is a uint8_t due to the enum - // being declared as an "enum class"! + // Хотя ECarTypes имеет тип uint8_t, код не будет скомпилирован из-за того, + // что перечисление было объявлено как класс перечисления. WriteByteToFile(InputCarType); } ////////////////////////////////////////// -// Classes and object-oriented programming +// Классы и объектно-ориентированное программирование ////////////////////////////////////////// -// First example of classes +// Пример классов #include -// Declare a class. -// Classes are usually declared in header (.h or .hpp) files. +// Объявление класса. +// Обычно классы объявляют в заголовочном (.h или .hpp) файле. 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. +// Все члены после этой сроки являются открытыми +// пока "private:" или "protected:" не будет объявлено. public: - // Default constructor + // Конструктор по умолчанию Dog(); - // Member function declarations (implementations to follow) - // Note that we use std::string here instead of placing + // Объявление функций-членов + // Обратите внимание, мы используем std::string здесь вместо использования // using namespace std; - // above. - // Never put a "using namespace" statement in a header. + // выше. + // Никогда не размещайте выражение "using namespace" в заголовке. 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. + // Функции, которые не изменяют состояние объекта, + // должны быть помечены как const. + // Это позволяет вызывать их если дана const ссылка на объект. + // Обратите внимание, функции должны быть явно объявлены как _virtual_ + // если вы хотите перегрузить их в производных классах. + // Функции не являются виртуальными по умолчания для повышения производительности. 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) - // The destructor should be virtual if a class is to be derived from; - // if it is not virtual, then the derived class' destructor will - // not be called if the object is destroyed through a base-class reference + // Наряду с конструкторами, в C++ есть деструкторы. + // Они вызываются, когда объект удаляется или выпадает с области видимости. + // Это активирует мощную парадигму программирования известную как RAII + // (смотрите ниже) + // Деструктор должен быть виртуальным, если класс будет производным. + // Если он не виртуальный, тогда деструктор производного класса не будет вызван + // если объект удален по ссылке или указателю базового класса. // or pointer. virtual ~Dog(); -}; // A semicolon must follow the class definition. +}; // Определение класса должно завершатся точкой с запятой. -// Class member functions are usually implemented in .cpp files. +// Функции-члены класса, как правило, реализуются в .cpp файлах. 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. +// Объекты (такие как строки) должны передаваться по ссылке если вы будете +// изменять их, или const-ссылке если нет. void Dog::setName(const std::string& dogsName) { name = dogsName; @@ -449,7 +446,7 @@ void Dog::setWeight(int dogsWeight) weight = dogsWeight; } -// Notice that "virtual" is only needed in the declaration, not the definition. +// Обратите внимание, "virtual" требуется только в объявлении, не в определении. void Dog::print() const { std::cout << "Dog is " << name << " and weighs " << weight << "kg\n"; @@ -461,35 +458,34 @@ Dog::~Dog() } int main() { - Dog myDog; // prints "A dog has been constructed" + Dog myDog; // Печатает "A dog has been constructed" myDog.setName("Barkley"); myDog.setWeight(10); - myDog.print(); // prints "Dog is Barkley and weighs 10 kg" + myDog.print(); // Печатает "Dog is Barkley and weighs 10 kg" return 0; -} // prints "Goodbye Barkley" +} // Печатает "Goodbye Barkley" -// Inheritance: +// Интерфейсы: -// This class inherits everything public and protected from the Dog class -// as well as private but may not directly access private members/methods -// without a public or protected method for doing so +// Этот класс наследует все открытые и защищенные члены класса Dog +// также как и все закрытые, но не может непосредственно получить доступ к закрытым +// членам\методам без открытых или защищенных методов для этого. 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. + // Переопределяем поведение функции печати для всех OwnedDog. Смотрите + // https://goo.gl/3kuH2x для боле общего введения, если вы не знакомы + // с концепцией полиморфизма подтипов (включения). + // Ключевое слово override является необязательным, но указывает что метод + // на самом деле перегружается в базовом классе. void print() const override; private: std::string owner; }; -// Meanwhile, in the corresponding .cpp file: +// Тем временем, в соответствующем .cpp файле: void OwnedDog::setOwner(const std::string& dogsOwner) { @@ -498,53 +494,54 @@ void OwnedDog::setOwner(const std::string& dogsOwner) void OwnedDog::print() const { - Dog::print(); // Call the print function in the base Dog class + Dog::print(); // Вызывает функцию print в базовом классе Dog std::cout << "Dog is owned by " << owner << "\n"; - // Prints "Dog is and weights " + // Печатает "Dog is and weights " // "Dog is owned by " } ////////////////////////////////////////// -// 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. +// В C++ вы можете перегрузить поведение таких операторов: +, -, *, / и др.. +// Это делается путем определения функции, которая вызывается, +// когда используется оператор. #include 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 со значениями + // по умолчанию (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. + // Создает новую точку, которая является суммой этой точки и rhs. return Point(x + rhs.x, y + rhs.y); } @@ -558,59 +555,58 @@ Point& Point::operator+=(const Point& rhs) int main () { Point up (0,1); Point right (1,0); - // This calls the Point + operator - // Point up calls the + (function) with right as its parameter + // Здесь происходит вызов оператора + класса Point + // Точка "up" вызывает + (функция) с параметром "right" Point result = up + right; - // Prints "Result is upright (1,1)" + // Печатает "Result is upright (1,1)" cout << "Result is upright (" << result.x << ',' << result.y << ")\n"; return 0; } ///////////////////// -// Templates +// Шаблоны ///////////////////// -// Templates in C++ are mostly used for generic programming, though they are -// much more powerful than generic constructs in other languages. They also -// support explicit and partial specialization and functional-style type -// classes; in fact, they are a Turing-complete functional language embedded -// in C++! +// Шаблоны в С++, в основном, используются для обобщенного программирования, хотя +// они гораздо более мощны чем дженерики в других языках. Они также поддерживают +// явные, частные и функциональные типы классов; на самом деле, они являются +// тьюринг-полным языком встроенным в C++! -// 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 Box { public: - // In this class, T can be used as any other type. + // В этом классе T может быть любого типа. void insert(const T&) { ... } }; -// During compilation, the compiler actually generates copies of each template -// with parameters substituted, 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 intBox; -// and you can use it as you would expect: +// и вы можете использовать его, как и ожидалось: intBox.insert(123); -// You can, of course, nest templates: +// Вы, конечно, можете использовать вложенные шаблоны: Box > boxOfBox; boxOfBox.insert(intBox); -// Until C++11, you had to place a space between the two '>'s, otherwise '>>' -// would be parsed as the right shift operator. +// Вплоть до С++11, вы должны были ставить пробел между двумя символами '>', иначе '>>' +// принимался парсером, как оператор правого сдвига. -// You will sometimes see +// Иногда вы можете увидеть // template -// instead. The 'class' keyword and 'typename' keywords are _mostly_ -// interchangeable in this case. For the full explanation, see +// вместо этого. В этом случае, ключевые слова 'class' и 'typename' _в основном_ +// взаимозаменяемыми. Для более подробной информации смотрите // http://en.wikipedia.org/wiki/Typename -// (yes, that keyword has its own Wikipedia page). +// (да-да, это ключевое слово имеет собственную страничку на вики). -// Similarly, a template function: +// Аналогичным образом, шаблонная функция: template void barkThreeTimes(const T& input) { @@ -619,115 +615,115 @@ void barkThreeTimes(const T& input) 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! +// Обратите внимание, что здесь ничего не указано о типе параметра. Компилятор +// будет генерировать и затем проверять тип каждый вызов шаблона, по-этому +// данная функция работает с любым типом 'T', который имеет метод 'bark'. Dog fluffy; fluffy.setName("Fluffy") -barkThreeTimes(fluffy); // Prints "Fluffy barks" three times. +barkThreeTimes(fluffy); // Печатает "Fluffy barks" три раза. -// Template parameters don't have to be classes: +//Параметры шаблона не должны быть классами: template 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!" +printMessage<20>(); // Печатает "Learn C++ in 20 minutes!" +printMessage<10>(); // Печатает "Learn C++ faster in only 10 minutes!" ///////////////////// -// 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 +// Стандартная библиотека предоставляет несколько типов исключений +// (смотрите http://en.cppreference.com/w/cpp/error/exception) +// но, в принципе, любой тип может быть брошен в качестве исключения. #include #include -// All exceptions thrown inside the _try_ block can be caught by subsequent -// _catch_ handlers. +// Все исключения брошены внутри блока _try_ могут быть пойманы в последующем блоке +// _catch_. try { - // Do not allocate exceptions on the heap using _new_. + // Не выделяйте память в куче для исключений с помощью ключевого слова _new_. throw std::runtime_error("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_ catch (...) { std::cout << "Unknown exception caught"; - throw; // Re-throws the exception + throw; // Повторный выброс исключения } /////// -// RAII +// Получение ресурса есть инициализация (RAII) /////// -// RAII stands for "Resource Acquisition 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. + FILE* fh = fopen(filename, "r"); // Открываем файл в режиме чтения. doSomethingWithTheFile(fh); doSomethingElseWithIt(fh); - fclose(fh); // Close the file handle. + fclose(fh); // Закрываем обработчик файла. } -// 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. +// К сожалению, вещи быстро осложняется обработкой ошибок. +// Предположим fopen может потерпеть неудачу, тогда doSomethingWithTheFile и +// doSomethingElseWithIt вернут коды ошибок если потерпят неудачу. +// (Исключения являются предпочтительным способом обработки ошибок, +// но некоторые программисты, особенно те, кто имеет большой опыт работы с С, +// не согласны с аргументами о полезности исключений). +// Теперь мы должны проверить каждый вызов на наличие ошибок и закрыть обработчик +// файла если таковы есть. 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. - return false; // Report that failure to the caller. + FILE* fh = fopen(filename, "r"); // Открывает файл в режиме чтения + if (fh == nullptr) // В случае неудачи возвращаемый указатель принимает null. + return false; // Сообщает об неудаче вызывающему. - // Assume each function returns false if it failed + // Предположим, каждая функция возвращает false в случае неудачи if (!doSomethingWithTheFile(fh)) { - fclose(fh); // Close the file handle so it doesn't leak. - return false; // Propagate the error. + fclose(fh); // Закрываем обработчик файл чтобы не было утечек + return false; // Сообщает об ошибке. } if (!doSomethingElseWithIt(fh)) { - fclose(fh); // Close the file handle so it doesn't leak. - return false; // Propagate the error. + fclose(fh); // Закрываем обработчик файл чтобы не было утечек + return false; // Сообщает об ошибке. } - fclose(fh); // Close the file handle so it doesn't leak. - return true; // Indicate success + fclose(fh); // Закрываем обработчик файл чтобы не было утечек + return true; // Указывает на успех } -// C programmers often clean this up a little bit using goto: +// C-программисты часто упорядочивают это с помощью goto: bool doSomethingWithAFile(const char* filename) { FILE* fh = fopen(filename, "r"); @@ -741,18 +737,18 @@ bool doSomethingWithAFile(const char* filename) goto failure; fclose(fh); // Close the file - return true; // Indicate success + return true; // Указывает на успех failure: fclose(fh); - return false; // Propagate the error + return false; // Сообщает об ошибке. } -// 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 + FILE* fh = fopen(filename, "r"); // Открываем файл в режиме чтения if (fh == nullptr) throw std::runtime_error("Could not open the file."); @@ -761,52 +757,51 @@ void doSomethingWithAFile(const char* filename) doSomethingElseWithIt(fh); } catch (...) { - fclose(fh); // Be sure to close the file if an error occurs. - throw; // Then re-throw the exception. + fclose(fh); // Убедитесь, что закрываете файл, если происходит ошибка. + throw; // Затем повторно бросает исключение. } 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 -// whenever an object falls out of scope. +// Сравните это с использованием класса потока файла (fstream) в С++, который +// использует свой деструктор чтобы закрыть файл. Еще раз взгляните выше, +// деструктор вызывается автоматически, когда объект выпадает из области видимости. void doSomethingWithAFile(const std::string& filename) { - // ifstream is short for input file stream - std::ifstream fh(filename); // Open the file + // ifstream определяет файловый поток + std::ifstream fh(filename); // Открыть файл - // 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 - -// containers with object keys of non-primitive values (custom classes) require -// compare function in the object itself or as a function pointer. Primitives -// have default comparators, but you can override it. +} // Здесь файл автоматически закрывается в деструкторе. + +// Это имеет _огромнейшие_ преимущества: +// 1. Неважно, что произойдет, +// ресурсы (в данном случае обработчик файлов) будут очищены. +// После того, как вы правильно напишите деструктор, +// Больше будет _не возможно_ закрыть обработчик файлов или допустить утечку. +// 2. Обратите внимание, что код намного проще. +// Деструктор закрывает файловый поток "за кулисами" и вам больше не нужно об +// этом беспокоится. +// 3. Код устойчив к исключениям. +// Исключение может быть брошено в любом месте в функции и это никак не повлияет +// на очистку. + +// Весь идиоматический код на С++ широко использует RAII для всех ресурсов. +// Дополнительные примеры включат +// - Использование памяти unique_ptr и shared_ptr +// - Контейнеры - стандартная библиотека связанных списков, векторы +// (т.е. самоизменяемые массивы), хэш-карты и все остальное автоматически +// уничтожается сразу-же, когда выходит за пределы области видимости. +// - Ипользование мютексов lock_guard и unique_lock + +// Контейнеры с пользовательскими классами в качестве ключей требуют +// функций-компаратор в самом объекте или как указатель на функцию. Примитивы +// имеют компараторы по умолчанию, но вы можете перегрузить их. class Foo { public: int j; @@ -817,81 +812,82 @@ struct compareFunction { return a.j < b.j; } }; -//this isn't allowed (although it can vary depending on compiler) -//std::map fooMap; +// это не допускается (хотя это может варьироваться в зависимости от компилятора) +// std::map fooMap; std::map fooMap; fooMap[Foo(1)] = 1; fooMap.find(Foo(1)); //true ///////////////////// -// 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! + virtual void bar(); // Перегружает Foo::bar! }; -// 0 == false == NULL (most of the time)! +// 0 == false == NULL (в основном)! 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. +*pt = 0; // Устанавливает значение указателя 'pt' в false. +pt = 0; // Устанавливает значение 'pt' в нулевой указатель. Обе линии проходят + // компиляцию без ошибок. -// nullptr is supposed to fix some of that issue: +// nullptr приходит на помощь: int* pt2 = new int; -*pt2 = nullptr; // Doesn't compile -pt2 = nullptr; // Sets pt2 to null. +*pt2 = nullptr; // Не пройдет компиляцию +pt2 = nullptr; // Устанавливает pt2 в null. -// There is an exception made for bools. -// This is to allow you to test for null pointers with if(!ptr), -// but as a consequence you can assign nullptr to a bool directly! -*pt = nullptr; // This still compiles, even though '*pt' is a bool! +// Существует исключение для булевых значений. +// Это позволит вам проверить указатели с помощью if(!ptr), +// но как следствие вы можете установить nullptr в bool напрямую! +*pt = nullptr; // Это по прежнему проходит компиляцию, даже если '*pt' - bool! // '=' != '=' != '='! -// Calls Foo::Foo(const Foo&) or some variant (see move semantics) copy -// constructor. +// Вызывает Foo::Foo(const Foo&) или некий вариант (смотрите "move semantics") +// копирования конструктора. 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." +// Вызывает Foo::Foo(const Foo&) или вариант, но копирует только часть 'Foo' из +// 'fooSub'. Любые другие члены 'fooSub' пропускаются. Иногда это ужасное поведение +// называют "object slicing." FooSub fooSub; Foo f1 = fooSub; -// Calls Foo::operator=(Foo&) or variant. +// Вызывает Foo::operator=(Foo&) или вариант. Foo f1; f1 = f2; -// How to truly clear a container: +// Как по-настоящему очистить контейнер: class Foo { ... }; vector v; for (int i = 0; i < 10; ++i) v.push_back(Foo()); -// Following line sets size of v to 0, but destructors don't get called -// and resources aren't released! +// В слудующей точке размер v устанавливается в 0, но деструктор не вызывается +// и не происходит очистка ресурсов! v.empty(); -v.push_back(Foo()); // New value is copied into the first Foo we inserted +v.push_back(Foo()); // Новые значения копируются в первый вставленный Foo -// Truly destroys all values in v. See section about temporary objects for -// explanation of why this works. +// Настоящие уничтожение всех значений v. Смотрите раздел о временном объекте +// для объяснения того, как это работает. v.swap(vector()); ``` -Further Reading: +Дальнейшее чтение: -An up-to-date language reference can be found at +Наиболее полное и обновленное руководство по С++ можно найти на -Additional resources may be found at +Дополнительные ресурсы могут быть найдены на -- cgit v1.2.3 From 0aaa5a232c8112775a23ba706347c31525c92c27 Mon Sep 17 00:00:00 2001 From: Bohdan Shtepan Date: Wed, 6 Apr 2016 03:07:54 +0300 Subject: Update ru-ru/c++-ru.html.markdown --- ru-ru/c++-ru.html.markdown | 183 ++++++++++++++++++++++----------------------- 1 file changed, 91 insertions(+), 92 deletions(-) diff --git a/ru-ru/c++-ru.html.markdown b/ru-ru/c++-ru.html.markdown index 5137ec1f..0cf580d5 100644 --- a/ru-ru/c++-ru.html.markdown +++ b/ru-ru/c++-ru.html.markdown @@ -21,7 +21,7 @@ C++ - компилируемый, статически типизированн - язык с поддержкой обобщенного программирования Хотя его синтаксис может показаться более трудным или сложным для понимания, чем в более современных языках, -он широко применяется т.к. код написанный на C++ компилируется в набор инструкций, которые могут быть выполнены напрямую +он широко применяется, так как код, написанный на C++, компилируется в набор инструкций, которые могут быть выполнены напрямую процессором. C++ широко используется для разработки программного обеспечения, являясь одним из самых популярных языков программирования. Область его применения включает создание операционных систем, разнообразных прикладных программ, драйверов устройств, приложений для встраиваемых систем, высокопроизводительных серверов, а также развлекательных приложений (игр). @@ -34,21 +34,21 @@ C++ - компилируемый, статически типизированн // C++ практически представляет собой надмножество C и имеет схожий синтаксис // для объявления переменных, примитивов и функций. -// Также как и в С, точкой входа в программу является функция с именем main, +// Так же, как и в С, точкой входа в программу является функция с именем main, // которая возвращает целочисленное значение. // Это значение является кодом ответа программы. // Смотрите https://goo.gl/JYGKyv для более подробной информации. int main(int argc, char** argv) { - // Аргументы командной строки переданные в программу хранятся в переменных - // argc и argv, также как и в C. + // Аргументы командной строки, переданные в программу, хранятся в переменных + // argc и argv, так же, как и в C. // argc указывает на количество аргументов, - // а argv является масивом C-подобных строк (char*), который непосредсвенно + // а argv является массивом C-подобных строк (char*), который непосредсвенно // содержит аргументы. // Первым аргументом всегда передается имя программы. - // argc и argv могут быть опущены если вы не планируете работать с аругментамы + // argc и argv могут быть опущены, если вы не планируете работать с аругментами // коммандной строки. - // Тогда сигнатура функции будет иметь следующий вид int main() + // Тогда сигнатура функции будет иметь следующий вид: int main() // Возвращаемое значение 0 указывает на успешное завершение программы. return 0; @@ -56,17 +56,17 @@ int main(int argc, char** argv) // Тем не менее, C++ имеет свои отличия: -// В C++, символьные литералы являются символами. +// В C++ символьные литералы имеют тип char. sizeof('c') == sizeof(char) == 1 -// В С, символьные литералы - целые числа. +// В C символьные литералы - целые числа. sizeof('c') == sizeof(int) -// C++ имеет строго прототипирование. +// C++ имеет строгое прототипирование. void func(); // функция, которая не принимает аргументов. -// In C +// В языке C void func(); // функция, которая может принять сколько угодно аргументов. // Использование nullptr вместо NULL в C++. @@ -124,7 +124,7 @@ int main() doSomethingWithInts(20, 5); // a = 20, b = 5 } -// Аргументы по умолчанию должен быть в конце списка аргументов. +// Аргументы по умолчанию должны быть в конце списка аргументов. void invalidDeclaration(int a = 1, int b) // Ошибка! { @@ -162,9 +162,9 @@ void foo() int main() { - // Включает все функци с пространства имен Second в текущую область видимости. + // Включает все функци из пространства имен Second в текущую область видимости. // Обратите внимание, что простой вызов foo() больше не работает, - // так как теперь не ясно вызываем ли мы foo с пространства имен Second или + // так как теперь не ясно, вызываем ли мы foo из пространства имен Second, или // из глобальной области видимости. using namespace Second; @@ -174,11 +174,11 @@ int main() } /////////////// -// Ввод/Вывод +// Ввод и вывод /////////////// -// Вводи и вывод в C++ использует потоки -// cin, cout и cerr предоставлнеы методами stdin, stdout и stderr. +// Ввод и вывод в C++ использует потоки +// cin, cout и cerr представляют потоки stdin, stdout и stderr. // << - оператор вставки, >> - оператор извлечения. #include // Включение файла для работы с потоками Ввода\Вывода. @@ -189,7 +189,7 @@ int main() { int myInt; - // Выводит stdout (или терминал\экран) + // Выводит в stdout (или в терминал/на экран) cout << "Enter your favorite number:\n"; // Принимает ввод cin >> myInt; @@ -208,7 +208,7 @@ int main() // Строки в C++ являются объектами и имеют много функций-членов. #include -using namespace std; // Строки также доступны в пространстве имен std (стандартная библиотек) +using namespace std; // Строки также доступны в пространстве имен std (стандартная библиотека) string myString = "Hello"; string myOtherString = " World"; @@ -227,7 +227,7 @@ cout << myString; // "Hello Dog" // Ссылки ///////////// -// В добавок к указателям доступных в C, +// Кроме указателей, доступных в C, // C++ имеет _ссылки_. // Это такой тип указателя, который не может быть переназначен после инициализации // и не может иметь значения null. @@ -241,11 +241,11 @@ string foo = "I am foo"; string bar = "I am bar"; -string& fooRef = foo; // Здесь создается указатель на foo. +string& fooRef = foo; // Здесь создается ссылка на foo. fooRef += ". Hi!"; // Изменяет foo по ссылке cout << fooRef; // Печатает "I am foo. Hi!" -// Не переназначает "fooRef". Это тоже самое как "foo = bar", и +// Не переназначает "fooRef". Это то же самое, что и "foo = bar", и // foo == "I am bar" // после этой строчки. cout << &fooRef << endl; // Печатает адрес foo @@ -256,31 +256,31 @@ cout << fooRef; // Печатает "I am bar" // Адрес fooRef остается тем же, то есть он по-прежнему ссылается на foo. -const string& barRef = bar; // Создает const со ссылкой на bar. -// Также как и C, значения const (и указателей и ссылок) не могут быть изменены. -barRef += ". Hi!"; // Ошибка, указатель const не может быть изменен. +const string& barRef = bar; // Создает константную ссылку. +// Так же, как и в C, константные значения (а также указатели и ссылки) не могут быть изменены. +barRef += ". Hi!"; // Ошибка, константная ссылка не может быть изменена. -// Обходной путь: Прежде чем мы рассмотрим указатели более детально, нам нужно ознакомится -// с концепцией известной как "временный объект". Представьте, что мы имеем следующий код +// Обходной путь: Прежде чем мы рассмотрим указатели более детально, нам нужно ознакомиться +// с концепцией, известной как "временный объект". Представьте, что мы имеем следующий код string tempObjectFun() { ... } string retVal = tempObjectFun(); -// Вот что на самом деле происходит во второй строе: +// Вот что на самом деле происходит во второй строке: // - tempObjectFun возвращает строковый объект -// - с возвращаемого объекта создается новая строка в качестве аргумента конструктору +// - из возвращаемого объекта создается новая строка в качестве аргумента конструктору // - возвращаемый объект уничтожается -// Возвращаемый объект называется временным объектом. Временные объекты создаются +// Возвращаемый объект называется временным объектом. Временные объекты создаются, // когда функция возвращает объект, и уничтожаются в конце выполнения обрамляющего // выражения (По крайней мере, так это описывает спецификация, хотя компиляторы могут // изменять это поведение. Для более подробной информации смотрите "оптимизация -// возвращаемого значения". Таким образом в этом коде: +// возвращаемого значения".) Таким образом в этом коде: foo(bar(tempObjectFun())) -// предполагая, что foo и bar существуют, объект возвращаемый tempObjectFun передается +// предполагая, что foo и bar существуют, объект, возвращаемый tempObjectFun, передается // в bar, и уничтожается перед вызовом foo. // Возвращаемся к указателям. Исключением для правила "в конце выполнения обрамляющего -// выражения" является временный объект привязанный к ссылке const, в этом случае +// выражения" является временный объект, привязанный к ссылке const, в этом случае // его жизненный цикл продлевается до текущей области видимости: void constReferenceTempObjectFun() { @@ -290,7 +290,7 @@ void constReferenceTempObjectFun() { } // В C++11 предоставлен еще один тип ссылок специально для временных объектов. -// objects. Вы не можете объявить переменную этого типа, но он имеет приоритет в +// objects. Вы не можете объявить переменную этого типа, но он имеет приоритет // в резолюции перегрузки: void someFun(string& s) { ... } // Обычная ссылка @@ -304,7 +304,7 @@ someFun(tempObjectFun()); // Выполняет версию с временн basic_string(const basic_string& other); basic_string(basic_string&& other); -// Идея в том, если мы конструируем новую строку из временного объекта (который +// Идея в том, что если мы конструируем новую строку из временного объекта (который // так или иначе будет уничтожен), мы можем использовать более эффективный конструктор, // который "спасает" части этой временной строки. Эта концепция была названа // "move semantics". @@ -313,7 +313,7 @@ basic_string(basic_string&& other); // Перечисления ///////////////////// -// Перечисления - способ объявления констант и установки их значений в основном +// Перечисления - способ объявления констант и установки их значений, в основном // использующийся для упрощения чтения кода. enum ECarTypes { @@ -346,7 +346,7 @@ void WriteByteToFile(uint8_t InputValue) void WritePreferredCarTypeToFile(ECarTypes InputCarType) { - // Перечисление неявно преобразуется в uint8_t из-за раннее объявленного + // Перечисление неявно преобразуется в uint8_t из-за ранее объявленного // типа перечисления. WriteByteToFile(InputCarType); } @@ -384,7 +384,7 @@ void WritePreferredCarTypeToFile(ECarTypes InputCarType) // Объявление класса. // Обычно классы объявляют в заголовочном (.h или .hpp) файле. class Dog { - // Переменный-члены и функции являются частными по умолчанию. + // Переменные-члены и функции являются приватными по умолчанию. std::string name; int weight; @@ -406,27 +406,26 @@ public: // Функции, которые не изменяют состояние объекта, // должны быть помечены как const. - // Это позволяет вызывать их если дана const ссылка на объект. - // Обратите внимание, функции должны быть явно объявлены как _virtual_ + // Это позволяет вызывать их, если дана const ссылка на объект. + // Обратите внимание, функции должны быть явно объявлены как _virtual_, // если вы хотите перегрузить их в производных классах. - // Функции не являются виртуальными по умолчания для повышения производительности. + // Функции не являются виртуальными по умолчанию для повышения производительности. virtual void print() const; - // Такде функции могут быть определены внутри тела класса. + // Также функции могут быть определены внутри тела класса. // Функции, определенные следующим образом, автоматически встроены. void bark() const { std::cout << name << " barks!\n"; } // Наряду с конструкторами, в C++ есть деструкторы. - // Они вызываются, когда объект удаляется или выпадает с области видимости. - // Это активирует мощную парадигму программирования известную как RAII + // Они вызываются, когда объект удаляется или выпадает из области видимости. + // Это активирует мощную парадигму программирования, известную как RAII // (смотрите ниже) // Деструктор должен быть виртуальным, если класс будет производным. - // Если он не виртуальный, тогда деструктор производного класса не будет вызван + // Если он не виртуальный, тогда деструктор производного класса не будет вызван, // если объект удален по ссылке или указателю базового класса. - // or pointer. virtual ~Dog(); -}; // Определение класса должно завершатся точкой с запятой. +}; // Определение класса должно завершаться точкой с запятой. // Функции-члены класса, как правило, реализуются в .cpp файлах. Dog::Dog() @@ -468,7 +467,7 @@ int main() { // Интерфейсы: // Этот класс наследует все открытые и защищенные члены класса Dog -// также как и все закрытые, но не может непосредственно получить доступ к закрытым +// так же, как и все закрытые, но не может непосредственно получить доступ к закрытым // членам\методам без открытых или защищенных методов для этого. class OwnedDog : public Dog { @@ -477,7 +476,7 @@ class OwnedDog : public Dog { // Переопределяем поведение функции печати для всех OwnedDog. Смотрите // https://goo.gl/3kuH2x для боле общего введения, если вы не знакомы // с концепцией полиморфизма подтипов (включения). - // Ключевое слово override является необязательным, но указывает что метод + // Ключевое слово override является необязательным, но указывает, что метод // на самом деле перегружается в базовом классе. void print() const override; @@ -527,9 +526,9 @@ public: Point (double a, double b) : x(a), y(b) - { /* Ничего не делайте кроме инициализации значений */ } + { /* Ничего не делайте, кроме инициализации значений */ } - // Перегружаем оперот +. + // Перегружаем оператор +. Point operator+(const Point& rhs) const; // Перегружаем оператор +=. @@ -568,9 +567,9 @@ int main () { ///////////////////// // Шаблоны в С++, в основном, используются для обобщенного программирования, хотя -// они гораздо более мощны чем дженерики в других языках. Они также поддерживают +// они гораздо более мощны, чем дженерики в других языках. Они также поддерживают // явные, частные и функциональные типы классов; на самом деле, они являются -// тьюринг-полным языком встроенным в C++! +// тьюринг-полным языком, встроенным в C++! // Мы начнем с наиболее распространенного типа обобщенного программирования. Чтобы // определить класс или функцию, которая принимает параметр типа: @@ -581,9 +580,9 @@ public: void insert(const T&) { ... } }; -// Во время компиляции, компилятор фактически генерирует копии каждого шаблона -// с замещенными параметрами, по-этому полное определение класса должно присутствовать -// при каждом вызове. Именно по-этому классы шаблонов полностью определены в +// Во время компиляции компилятор фактически генерирует копии каждого шаблона +// с замещенными параметрами, поэтому полное определение класса должно присутствовать +// при каждом вызове. Именно поэтому классы шаблонов полностью определены в // заголовочных файлах. // Чтобы создать экземпляр класса шаблона на стеке: @@ -597,11 +596,11 @@ Box > boxOfBox; boxOfBox.insert(intBox); // Вплоть до С++11, вы должны были ставить пробел между двумя символами '>', иначе '>>' -// принимался парсером, как оператор правого сдвига. +// принимался парсером, как оператор сдвига вправо. // Иногда вы можете увидеть // template -// вместо этого. В этом случае, ключевые слова 'class' и 'typename' _в основном_ +// вместо этого. В этом случае ключевые слова 'class' и 'typename' _в основном_ // взаимозаменяемыми. Для более подробной информации смотрите // http://en.wikipedia.org/wiki/Typename // (да-да, это ключевое слово имеет собственную страничку на вики). @@ -616,11 +615,11 @@ void barkThreeTimes(const T& input) } // Обратите внимание, что здесь ничего не указано о типе параметра. Компилятор -// будет генерировать и затем проверять тип каждый вызов шаблона, по-этому +// будет генерировать и затем проверять на тип каждый вызов шаблона, поэтому // данная функция работает с любым типом 'T', который имеет метод 'bark'. Dog fluffy; -fluffy.setName("Fluffy") +fluffy.setName("Fluffy"); barkThreeTimes(fluffy); // Печатает "Fluffy barks" три раза. //Параметры шаблона не должны быть классами: @@ -652,20 +651,20 @@ printMessage<10>(); // Печатает "Learn C++ faster in only 10 minutes!" #include #include -// Все исключения брошены внутри блока _try_ могут быть пойманы в последующем блоке +// Все исключения, брошенные в блоке _try_ могут быть пойманы в последующем блоке // _catch_. try { // Не выделяйте память в куче для исключений с помощью ключевого слова _new_. throw std::runtime_error("A problem occurred"); } -// Поймайте исключение по константной ссылке, если они являются объектами +// Поймайте исключение по константной ссылке, если оно является объектом catch (const std::exception& ex) { std::cout << ex.what(); } -// Ловит любое исключение не пойманное предыдущим блоком _catch_ +// Ловит любое исключение, не пойманное предыдущим блоком _catch_ catch (...) { std::cout << "Unknown exception caught"; @@ -681,7 +680,7 @@ catch (...) // некоторого ресурса неразрывно совмещается с инициализацией, а освобождение - // с уничтожением объекта. -// Чтобы понять на сколько это полезно, +// Чтобы понять, на сколько это полезно, // рассмотрим функцию, которая использует обработчик файлов в С: void doSomethingWithAFile(const char* filename) { @@ -695,31 +694,31 @@ void doSomethingWithAFile(const char* filename) fclose(fh); // Закрываем обработчик файла. } -// К сожалению, вещи быстро осложняется обработкой ошибок. -// Предположим fopen может потерпеть неудачу, тогда doSomethingWithTheFile и -// doSomethingElseWithIt вернут коды ошибок если потерпят неудачу. +// К сожалению, вещи быстро осложняются обработкой ошибок. +// Предположим, fopen может потерпеть неудачу, тогда doSomethingWithTheFile и +// doSomethingElseWithIt вернут коды ошибок, если потерпят неудачу. // (Исключения являются предпочтительным способом обработки ошибок, // но некоторые программисты, особенно те, кто имеет большой опыт работы с С, // не согласны с аргументами о полезности исключений). // Теперь мы должны проверить каждый вызов на наличие ошибок и закрыть обработчик -// файла если таковы есть. +// файла, если он есть. bool doSomethingWithAFile(const char* filename) { FILE* fh = fopen(filename, "r"); // Открывает файл в режиме чтения - if (fh == nullptr) // В случае неудачи возвращаемый указатель принимает null. - return false; // Сообщает об неудаче вызывающему. + if (fh == nullptr) // В случае неудачи возвращаемый указатель принимает значение null. + return false; // Сообщает о неудаче вызывающему. // Предположим, каждая функция возвращает false в случае неудачи if (!doSomethingWithTheFile(fh)) { - fclose(fh); // Закрываем обработчик файл чтобы не было утечек + fclose(fh); // Закрываем обработчик файла, чтобы не было утечек return false; // Сообщает об ошибке. } if (!doSomethingElseWithIt(fh)) { - fclose(fh); // Закрываем обработчик файл чтобы не было утечек + fclose(fh); // Закрываем обработчик файла, чтобы не было утечек return false; // Сообщает об ошибке. } - fclose(fh); // Закрываем обработчик файл чтобы не было утечек + fclose(fh); // Закрываем обработчик файла, чтобы не было утечек return true; // Указывает на успех } @@ -736,7 +735,7 @@ bool doSomethingWithAFile(const char* filename) if (!doSomethingElseWithIt(fh)) goto failure; - fclose(fh); // Close the file + fclose(fh); // Закрываем файл. return true; // Указывает на успех failure: @@ -761,12 +760,12 @@ void doSomethingWithAFile(const char* filename) throw; // Затем повторно бросает исключение. } - fclose(fh); // Close the file + fclose(fh); // Закрываем файл. // Успех } // Сравните это с использованием класса потока файла (fstream) в С++, который -// использует свой деструктор чтобы закрыть файл. Еще раз взгляните выше, +// использует свой деструктор, чтобы закрыть файл. Еще раз взгляните выше, // деструктор вызывается автоматически, когда объект выпадает из области видимости. void doSomethingWithAFile(const std::string& filename) { @@ -781,26 +780,26 @@ void doSomethingWithAFile(const std::string& filename) // Это имеет _огромнейшие_ преимущества: // 1. Неважно, что произойдет, -// ресурсы (в данном случае обработчик файлов) будут очищены. -// После того, как вы правильно напишите деструктор, -// Больше будет _не возможно_ закрыть обработчик файлов или допустить утечку. +// ресурсы (в данном случае дескриптор файла) будут очищены. +// После того, как вы правильно напишете деструктор, +// Больше будет _невозможно_ закрыть обработчик файлов или допустить утечку. // 2. Обратите внимание, что код намного проще. -// Деструктор закрывает файловый поток "за кулисами" и вам больше не нужно об -// этом беспокоится. +// Деструктор закрывает файловый поток "за кулисами", и вам больше не нужно об +// этом беспокоиться. // 3. Код устойчив к исключениям. -// Исключение может быть брошено в любом месте в функции и это никак не повлияет +// Исключение может быть брошено в любом месте в функции, и это никак не повлияет // на очистку. // Весь идиоматический код на С++ широко использует RAII для всех ресурсов. -// Дополнительные примеры включат +// Дополнительные примеры включат: // - Использование памяти unique_ptr и shared_ptr // - Контейнеры - стандартная библиотека связанных списков, векторы -// (т.е. самоизменяемые массивы), хэш-карты и все остальное автоматически -// уничтожается сразу-же, когда выходит за пределы области видимости. -// - Ипользование мютексов lock_guard и unique_lock +// (т.е. самоизменяемые массивы), хэш-таблицы и все остальное автоматически +// уничтожается сразу же, когда выходит за пределы области видимости. +// - Ипользование мьютексов lock_guard и unique_lock // Контейнеры с пользовательскими классами в качестве ключей требуют -// функций-компаратор в самом объекте или как указатель на функцию. Примитивы +// сравнивающих функций в самом объекте или как указатель на функцию. Примитивы // имеют компараторы по умолчанию, но вы можете перегрузить их. class Foo { public: @@ -822,7 +821,7 @@ fooMap.find(Foo(1)); //true // Веселые вещи ///////////////////// -// Аспекты С++, которые могут быть удивительными для новичком (и даже для некоторых +// Аспекты С++, которые могут быть удивительными для новичков (и даже для некоторых // ветеранов). Этот раздел, к сожалению, очень неполон. С++ является одним из самых // простых языков, где очень легко выстрелить себе в ногу. @@ -838,7 +837,7 @@ class FooSub : public Foo { // 0 == false == NULL (в основном)! bool* pt = new bool; *pt = 0; // Устанавливает значение указателя 'pt' в false. -pt = 0; // Устанавливает значение 'pt' в нулевой указатель. Обе линии проходят +pt = 0; // Устанавливает значение 'pt' в нулевой указатель. Обе строки проходят // компиляцию без ошибок. // nullptr приходит на помощь: @@ -875,17 +874,17 @@ vector v; for (int i = 0; i < 10; ++i) v.push_back(Foo()); -// В слудующей точке размер v устанавливается в 0, но деструктор не вызывается +// В следующей точке размер v устанавливается в 0, но деструктор не вызывается // и не происходит очистка ресурсов! v.empty(); v.push_back(Foo()); // Новые значения копируются в первый вставленный Foo -// Настоящие уничтожение всех значений v. Смотрите раздел о временном объекте +// Настоящее уничтожение всех значений v. Смотрите раздел о временном объекте // для объяснения того, как это работает. v.swap(vector()); ``` -Дальнейшее чтение: +## Дальнейшее чтение: Наиболее полное и обновленное руководство по С++ можно найти на -- cgit v1.2.3