Update ru-ru/c++-ru.html.markdown

This commit is contained in:
Bohdan Shtepan 2016-04-06 03:07:54 +03:00
parent 8abfffd183
commit 0aaa5a232c

View File

@ -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 <iostream> // Включение файла для работы с потоками Ввода\Вывода.
@ -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 <string>
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<Box<int> > boxOfBox;
boxOfBox.insert(intBox);
// Вплоть до С++11, вы должны были ставить пробел между двумя символами '>', иначе '>>'
// принимался парсером, как оператор правого сдвига.
// принимался парсером, как оператор сдвига вправо.
// Иногда вы можете увидеть
// template<typename T>
// вместо этого. В этом случае, ключевые слова '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 <exception>
#include <stdexcept>
// Все исключения брошены внутри блока _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<Foo> 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<Foo>());
```
Дальнейшее чтение:
## Дальнейшее чтение:
Наиболее полное и обновленное руководство по С++ можно найти на
<http://cppreference.com/w/cpp>