diff options
| -rw-r--r-- | ru-ru/c++-ru.html.markdown | 582 | 
1 files 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 <iostream> // Include for I/O streams +#include <iostream> // Включение файла для работы с потоками Ввода\Вывода. -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 <myInt>" +   // напечатает "Your favorite number is <myInt>"      cerr << "Used for error messages";  } @@ -205,35 +205,35 @@ int main()  // Строки  ////////// -// Strings in C++ are objects and have many member functions +// Строки в C++ являются объектами и имеют много функций-членов.  #include <string> -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 <iostream> -// 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 <name> and weights <weight>" +    // Печатает "Dog is <name> and weights <weight>"      //        "Dog is owned by <owner>"  }  ////////////////////////////////////////// -// Initialization and Operator Overloading +// Инициализация и перегрузка операторов.  ////////////////////////////////////////// -// In C++ you can overload the behavior of operators such as +, -, *, /, etc. -// This is done by defining a function which is called -// whenever the operator is used. +// В C++ вы можете перегрузить поведение таких операторов: +, -, *, / и др.. +// Это делается путем определения функции, которая вызывается, +// когда используется оператор.  #include <iostream>  using namespace std;  class Point {  public: -    // Member variables can be given default values in this manner. +    // Значения по умолчанию для переменных-членов могут быть установлены +	// следующим образом.      double x = 0;      double y = 0; -    // Define a default constructor which does nothing -    // but initialize the Point to the default value (0, 0) +    // Определяем новый конструктор, который инициализирует Point со значениями +    // по умолчанию (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 T>  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<int> intBox; -// and you can use it as you would expect: +// и вы можете использовать его, как и ожидалось:  intBox.insert(123); -// You can, of course, nest templates: +// Вы, конечно, можете использовать вложенные шаблоны:  Box<Box<int> > boxOfBox;  boxOfBox.insert(intBox); -// 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<typename T> -// 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<class T>  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<int Y>  void printMessage() {    cout << "Learn C++ in " << Y << " minutes!" << endl;  } -// And you can explicitly specialize templates for more efficient code. Of -// course, most real-world uses of specialization are not as trivial as this. -// Note that you still need to declare the function (or class) as a template -// even if you explicitly specified all parameters. +// В конце концов, вы можете явно специализировать шаблоны для более эффективного +// кода. Конечно, большинство реальных случаев использования специализации +// не так тривиально, как это. Обратите внимание, вам все еще нужно явно объявить +// функцию (или класс) в качестве шаблона, даже если вы явно указали все параметры.  template<>  void printMessage<10>() {    cout << "Learn C++ faster in only 10 minutes!" << endl;  } -printMessage<20>();  // Prints "Learn C++ in 20 minutes!" -printMessage<10>();  // Prints "Learn C++ faster in only 10 minutes!" +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 <exception>  #include <stdexcept> -// 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<Foo, int> fooMap; +// это не допускается (хотя это может варьироваться в зависимости от компилятора) +// std::map<Foo, int> fooMap;  std::map<Foo, int, compareFunction> 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<Foo> 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<Foo>());  ``` -Further Reading: +Дальнейшее чтение: -An up-to-date language reference can be found at +Наиболее полное и обновленное руководство по С++ можно найти на  <http://cppreference.com/w/cpp> -Additional resources may be found at <http://cplusplus.com> +Дополнительные ресурсы могут быть найдены на <http://cplusplus.com> | 
