summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ru-ru/c++-ru.html.markdown582
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>