diff options
Diffstat (limited to 'ru-ru')
-rw-r--r-- | ru-ru/c++-ru.html.markdown | 892 | ||||
-rw-r--r-- | ru-ru/markdown-ru.html.markdown | 300 | ||||
-rw-r--r-- | ru-ru/php-ru.html.markdown | 2 |
3 files changed, 1081 insertions, 113 deletions
diff --git a/ru-ru/c++-ru.html.markdown b/ru-ru/c++-ru.html.markdown new file mode 100644 index 00000000..0cf580d5 --- /dev/null +++ b/ru-ru/c++-ru.html.markdown @@ -0,0 +1,892 @@ +--- +language: c++ +filename: learncpp-ru.cpp +contributors: + - ["Steven Basart", "http://github.com/xksteven"] + - ["Matt Kline", "https://github.com/mrkline"] + - ["Geoff Liu", "http://geoffliu.me"] + - ["Connor Waters", "http://github.com/connorwaters"] +translators: + - ["Bohdan Shtepan", "http://modern-dev.com"] +lang: ru-ru +--- + +C++ - компилируемый, статически типизированный язык программирования общего назначения, который, +[как заявляет создатель языка Бьёрн Страуструп](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Keynote), +был разработан как + +- "лучшая замена C" +- язык с поддержкой абстракции данных +- язык с поддержкой объектно-ориентированого программирования +- язык с поддержкой обобщенного программирования + +Хотя его синтаксис может показаться более трудным или сложным для понимания, чем в более современных языках, +он широко применяется, так как код, написанный на C++, компилируется в набор инструкций, которые могут быть выполнены напрямую +процессором. C++ широко используется для разработки программного обеспечения, являясь одним из самых популярных языков +программирования. Область его применения включает создание операционных систем, разнообразных прикладных программ, драйверов +устройств, приложений для встраиваемых систем, высокопроизводительных серверов, а также развлекательных приложений (игр). + +```c++ +////////////////// +// Сравнение с C +////////////////// + +// C++ практически представляет собой надмножество C и имеет схожий синтаксис +// для объявления переменных, примитивов и функций. + +// Так же, как и в С, точкой входа в программу является функция с именем main, +// которая возвращает целочисленное значение. +// Это значение является кодом ответа программы. +// Смотрите https://goo.gl/JYGKyv для более подробной информации. +int main(int argc, char** argv) +{ + // Аргументы командной строки, переданные в программу, хранятся в переменных + // argc и argv, так же, как и в C. + // argc указывает на количество аргументов, + // а argv является массивом C-подобных строк (char*), который непосредсвенно + // содержит аргументы. + // Первым аргументом всегда передается имя программы. + // argc и argv могут быть опущены, если вы не планируете работать с аругментами + // коммандной строки. + // Тогда сигнатура функции будет иметь следующий вид: int main() + + // Возвращаемое значение 0 указывает на успешное завершение программы. + return 0; +} + +// Тем не менее, C++ имеет свои отличия: + +// В C++ символьные литералы имеют тип char. +sizeof('c') == sizeof(char) == 1 + +// В C символьные литералы - целые числа. +sizeof('c') == sizeof(int) + + +// C++ имеет строгое прототипирование. +void func(); // функция, которая не принимает аргументов. + +// В языке C +void func(); // функция, которая может принять сколько угодно аргументов. + +// Использование nullptr вместо NULL в C++. +int* ip = nullptr; + +// Стандартные заголовочные файлы С доступны в С++, +// но с префиксом "с" и не имеют суффикса .h. +#include <cstdio> + +int main() +{ + printf("Hello, world!\n"); + return 0; +} + +/////////////////////// +// Перегрузка функций +/////////////////////// + +// С++ поддерживает перегрузку функций, при условии, +// что каждая функция принимает различные параметры. + +void print(char const* myString) +{ + printf("String %s\n", myString); +} + +void print(int myInt) +{ + printf("My int is %d", myInt); +} + +int main() +{ + print("Hello"); // Использование void print(const char*) + print(15); // Использование void print(int) +} + +///////////////////////////// +// Аргументы функций по умолчанию +///////////////////////////// + +// Вы можете предоставить аргументы по умолчанию для функции, +// если они не предоставлены при вызове функции. + +void doSomethingWithInts(int a = 1, int b = 4) +{ + // Здесь что-то делаем с числами +} + +int main() +{ + doSomethingWithInts(); // a = 1, b = 4 + doSomethingWithInts(20); // a = 20, b = 4 + doSomethingWithInts(20, 5); // a = 20, b = 5 +} + +// Аргументы по умолчанию должны быть в конце списка аргументов. + +void invalidDeclaration(int a = 1, int b) // Ошибка! +{ +} + + +///////////// +// Пространства имен +///////////// + +// Пространства имен предоставляют отдельные области для переменной, +// функции и других объявлений. +// Пространства имен могут быть вложенными. + +namespace First { + namespace Nested { + void foo() + { + printf("This is First::Nested::foo\n"); + } + } // конец пространства имен Nested +} // конец пространства имен First + +namespace Second { + void foo() + { + printf("This is Second::foo\n") + } +} + +void foo() +{ + printf("This is global foo\n"); +} + +int main() +{ + // Включает все функци из пространства имен Second в текущую область видимости. + // Обратите внимание, что простой вызов foo() больше не работает, + // так как теперь не ясно, вызываем ли мы foo из пространства имен Second, или + // из глобальной области видимости. + using namespace Second; + + Second::foo(); // напечатает "This is Second::foo" + First::Nested::foo(); // напечатает "This is First::Nested::foo" + ::foo(); // напечатает "This is global foo" +} + +/////////////// +// Ввод и вывод +/////////////// + +// Ввод и вывод в C++ использует потоки +// cin, cout и cerr представляют потоки stdin, stdout и stderr. +// << - оператор вставки, >> - оператор извлечения. + +#include <iostream> // Включение файла для работы с потоками Ввода\Вывода. + +using namespace std; // Потоки доступны в пространстве имен std (стандартная библиотека) + +int main() +{ + int myInt; + + // Выводит в stdout (или в терминал/на экран) + cout << "Enter your favorite number:\n"; + // Принимает ввод + cin >> myInt; + + // cout может принимать форматирование + cout << "Your favorite number is " << myInt << "\n"; + // напечатает "Your favorite number is <myInt>" + + cerr << "Used for error messages"; +} + +////////// +// Строки +////////// + +// Строки в C++ являются объектами и имеют много функций-членов. +#include <string> + +using namespace std; // Строки также доступны в пространстве имен std (стандартная библиотека) + +string myString = "Hello"; +string myOtherString = " World"; + +// + используется для конкатенации строк. +cout << myString + myOtherString; // "Hello World" + +cout << myString + " You"; // "Hello You" + +// Строки в C++ могут изменяться и имеют семантику значений. +myString.append(" Dog"); +cout << myString; // "Hello Dog" + + +///////////// +// Ссылки +///////////// + +// Кроме указателей, доступных в C, +// C++ имеет _ссылки_. +// Это такой тип указателя, который не может быть переназначен после инициализации +// и не может иметь значения null. +// Ссылки имеют схожий с переменными синтаксис: +// * больше не используется для разыменования и +// & (адрес) не используется для назначения. + +using namespace std; + +string foo = "I am foo"; +string bar = "I am bar"; + + +string& fooRef = foo; // Здесь создается ссылка на foo. +fooRef += ". Hi!"; // Изменяет foo по ссылке +cout << fooRef; // Печатает "I am foo. Hi!" + +// Не переназначает "fooRef". Это то же самое, что и "foo = bar", и +// foo == "I am bar" +// после этой строчки. +cout << &fooRef << endl; // Печатает адрес foo +fooRef = bar; +cout << &fooRef << endl; // По-прежнему печатает адрес foo +cout << fooRef; // Печатает "I am bar" + +// Адрес fooRef остается тем же, то есть он по-прежнему ссылается на foo. + + +const string& barRef = bar; // Создает константную ссылку. +// Так же, как и в C, константные значения (а также указатели и ссылки) не могут быть изменены. +barRef += ". Hi!"; // Ошибка, константная ссылка не может быть изменена. + +// Обходной путь: Прежде чем мы рассмотрим указатели более детально, нам нужно ознакомиться +// с концепцией, известной как "временный объект". Представьте, что мы имеем следующий код +string tempObjectFun() { ... } +string retVal = tempObjectFun(); + +// Вот что на самом деле происходит во второй строке: +// - tempObjectFun возвращает строковый объект +// - из возвращаемого объекта создается новая строка в качестве аргумента конструктору +// - возвращаемый объект уничтожается +// Возвращаемый объект называется временным объектом. Временные объекты создаются, +// когда функция возвращает объект, и уничтожаются в конце выполнения обрамляющего +// выражения (По крайней мере, так это описывает спецификация, хотя компиляторы могут +// изменять это поведение. Для более подробной информации смотрите "оптимизация +// возвращаемого значения".) Таким образом в этом коде: +foo(bar(tempObjectFun())) + +// предполагая, что foo и bar существуют, объект, возвращаемый tempObjectFun, передается +// в bar, и уничтожается перед вызовом foo. + +// Возвращаемся к указателям. Исключением для правила "в конце выполнения обрамляющего +// выражения" является временный объект, привязанный к ссылке const, в этом случае +// его жизненный цикл продлевается до текущей области видимости: + +void constReferenceTempObjectFun() { + // constRef получает временный объект, и он действителен до конца этой функции. + const string& constRef = tempObjectFun(); + ... +} + +// В C++11 предоставлен еще один тип ссылок специально для временных объектов. +// objects. Вы не можете объявить переменную этого типа, но он имеет приоритет +// в резолюции перегрузки: + +void someFun(string& s) { ... } // Обычная ссылка +void someFun(string&& s) { ... } // Ссылка на временный объект + +string foo; +someFun(foo); // Выполняет версию с обычной ссылкой +someFun(tempObjectFun()); // Выполняет версию с временной ссылкой. + +// Например, существуют следующие две версии конструктора std::basic_string: +basic_string(const basic_string& other); +basic_string(basic_string&& other); + +// Идея в том, что если мы конструируем новую строку из временного объекта (который +// так или иначе будет уничтожен), мы можем использовать более эффективный конструктор, +// который "спасает" части этой временной строки. Эта концепция была названа +// "move semantics". + +///////////////////// +// Перечисления +///////////////////// + +// Перечисления - способ объявления констант и установки их значений, в основном +// использующийся для упрощения чтения кода. +enum ECarTypes +{ + Sedan, + Hatchback, + SUV, + Wagon +}; + +ECarTypes GetPreferredCarType() +{ + return ECarTypes::Hatchback; +} + +// На момент выхода C++11 есть простой способ назначения типа перечисления, что +// полезно в случае сериализации данных и преобразований между конечным типом и +// соответствующими константами. +enum ECarTypes : uint8_t +{ + Sedan, // 0 + Hatchback, // 1 + SUV = 254, // 254 + Hybrid // 255 +}; + +void WriteByteToFile(uint8_t InputValue) +{ + // Сериализуем InputValue в файл +} + +void WritePreferredCarTypeToFile(ECarTypes InputCarType) +{ + // Перечисление неявно преобразуется в uint8_t из-за ранее объявленного + // типа перечисления. + WriteByteToFile(InputCarType); +} + +// С другой стороны, чтобы избежать случайного приведения к целочисленному типу или +// другому перечислению, вы можете создать класс перечисления, который не будет +// преобразовываться неявно. +enum class ECarTypes : uint8_t +{ + Sedan, // 0 + Hatchback, // 1 + SUV = 254, // 254 + Hybrid // 255 +}; + +void WriteByteToFile(uint8_t InputValue) +{ + // Сериализуем InputValue в файл +} + +void WritePreferredCarTypeToFile(ECarTypes InputCarType) +{ + // Хотя ECarTypes имеет тип uint8_t, код не будет скомпилирован из-за того, + // что перечисление было объявлено как класс перечисления. + WriteByteToFile(InputCarType); +} + +////////////////////////////////////////// +// Классы и объектно-ориентированное программирование +////////////////////////////////////////// + +// Пример классов +#include <iostream> + +// Объявление класса. +// Обычно классы объявляют в заголовочном (.h или .hpp) файле. +class Dog { + // Переменные-члены и функции являются приватными по умолчанию. + std::string name; + int weight; + +// Все члены после этой сроки являются открытыми +// пока "private:" или "protected:" не будет объявлено. +public: + + // Конструктор по умолчанию + Dog(); + + // Объявление функций-членов + // Обратите внимание, мы используем std::string здесь вместо использования + // using namespace std; + // выше. + // Никогда не размещайте выражение "using namespace" в заголовке. + void setName(const std::string& dogsName); + + void setWeight(int dogsWeight); + + // Функции, которые не изменяют состояние объекта, + // должны быть помечены как const. + // Это позволяет вызывать их, если дана const ссылка на объект. + // Обратите внимание, функции должны быть явно объявлены как _virtual_, + // если вы хотите перегрузить их в производных классах. + // Функции не являются виртуальными по умолчанию для повышения производительности. + virtual void print() const; + + // Также функции могут быть определены внутри тела класса. + // Функции, определенные следующим образом, автоматически встроены. + void bark() const { std::cout << name << " barks!\n"; } + + // Наряду с конструкторами, в C++ есть деструкторы. + // Они вызываются, когда объект удаляется или выпадает из области видимости. + // Это активирует мощную парадигму программирования, известную как RAII + // (смотрите ниже) + // Деструктор должен быть виртуальным, если класс будет производным. + // Если он не виртуальный, тогда деструктор производного класса не будет вызван, + // если объект удален по ссылке или указателю базового класса. + virtual ~Dog(); + +}; // Определение класса должно завершаться точкой с запятой. + +// Функции-члены класса, как правило, реализуются в .cpp файлах. +Dog::Dog() +{ + std::cout << "A dog has been constructed\n"; +} + +// Объекты (такие как строки) должны передаваться по ссылке если вы будете +// изменять их, или const-ссылке если нет. +void Dog::setName(const std::string& dogsName) +{ + name = dogsName; +} + +void Dog::setWeight(int dogsWeight) +{ + weight = dogsWeight; +} + +// Обратите внимание, "virtual" требуется только в объявлении, не в определении. +void Dog::print() const +{ + std::cout << "Dog is " << name << " and weighs " << weight << "kg\n"; +} + +Dog::~Dog() +{ + cout << "Goodbye " << name << "\n"; +} + +int main() { + Dog myDog; // Печатает "A dog has been constructed" + myDog.setName("Barkley"); + myDog.setWeight(10); + myDog.print(); // Печатает "Dog is Barkley and weighs 10 kg" + return 0; +} // Печатает "Goodbye Barkley" + +// Интерфейсы: + +// Этот класс наследует все открытые и защищенные члены класса Dog +// так же, как и все закрытые, но не может непосредственно получить доступ к закрытым +// членам\методам без открытых или защищенных методов для этого. +class OwnedDog : public Dog { + + void setOwner(const std::string& dogsOwner); + + // Переопределяем поведение функции печати для всех OwnedDog. Смотрите + // https://goo.gl/3kuH2x для боле общего введения, если вы не знакомы + // с концепцией полиморфизма подтипов (включения). + // Ключевое слово override является необязательным, но указывает, что метод + // на самом деле перегружается в базовом классе. + void print() const override; + +private: + std::string owner; +}; + +// Тем временем, в соответствующем .cpp файле: + +void OwnedDog::setOwner(const std::string& dogsOwner) +{ + owner = dogsOwner; +} + +void OwnedDog::print() const +{ + Dog::print(); // Вызывает функцию print в базовом классе Dog + std::cout << "Dog is owned by " << owner << "\n"; + // Печатает "Dog is <name> and weights <weight>" + // "Dog is owned by <owner>" +} + +////////////////////////////////////////// +// Инициализация и перегрузка операторов. +////////////////////////////////////////// + +// В C++ вы можете перегрузить поведение таких операторов: +, -, *, / и др.. +// Это делается путем определения функции, которая вызывается, +// когда используется оператор. + +#include <iostream> +using namespace std; + +class Point { +public: + // Значения по умолчанию для переменных-членов могут быть установлены + // следующим образом. + double x = 0; + double y = 0; + + // Определяем новый конструктор, который инициализирует Point со значениями + // по умолчанию (0, 0) + Point() { }; + + // Следующий синтаксис известен как список инициализации и является верным способом + // инициализировать значения членов класса. + Point (double a, double b) : + x(a), + y(b) + { /* Ничего не делайте, кроме инициализации значений */ } + + // Перегружаем оператор +. + Point operator+(const Point& rhs) const; + + // Перегружаем оператор +=. + Point& operator+=(const Point& rhs); + + // Имеет смысл добавить перегрузку операторов - и -=, + // но для краткости мы опустим эти детали. +}; + +Point Point::operator+(const Point& rhs) const +{ + // Создает новую точку, которая является суммой этой точки и rhs. + return Point(x + rhs.x, y + rhs.y); +} + +Point& Point::operator+=(const Point& rhs) +{ + x += rhs.x; + y += rhs.y; + return *this; +} + +int main () { + Point up (0,1); + Point right (1,0); + // Здесь происходит вызов оператора + класса Point + // Точка "up" вызывает + (функция) с параметром "right" + Point result = up + right; + // Печатает "Result is upright (1,1)" + cout << "Result is upright (" << result.x << ',' << result.y << ")\n"; + return 0; +} + +///////////////////// +// Шаблоны +///////////////////// + +// Шаблоны в С++, в основном, используются для обобщенного программирования, хотя +// они гораздо более мощны, чем дженерики в других языках. Они также поддерживают +// явные, частные и функциональные типы классов; на самом деле, они являются +// тьюринг-полным языком, встроенным в C++! + +// Мы начнем с наиболее распространенного типа обобщенного программирования. Чтобы +// определить класс или функцию, которая принимает параметр типа: +template<class T> +class Box { +public: + // В этом классе T может быть любого типа. + void insert(const T&) { ... } +}; + +// Во время компиляции компилятор фактически генерирует копии каждого шаблона +// с замещенными параметрами, поэтому полное определение класса должно присутствовать +// при каждом вызове. Именно поэтому классы шаблонов полностью определены в +// заголовочных файлах. + +// Чтобы создать экземпляр класса шаблона на стеке: +Box<int> intBox; + +// и вы можете использовать его, как и ожидалось: +intBox.insert(123); + +// Вы, конечно, можете использовать вложенные шаблоны: +Box<Box<int> > boxOfBox; +boxOfBox.insert(intBox); + +// Вплоть до С++11, вы должны были ставить пробел между двумя символами '>', иначе '>>' +// принимался парсером, как оператор сдвига вправо. + +// Иногда вы можете увидеть +// template<typename T> +// вместо этого. В этом случае ключевые слова 'class' и 'typename' _в основном_ +// взаимозаменяемыми. Для более подробной информации смотрите +// http://en.wikipedia.org/wiki/Typename +// (да-да, это ключевое слово имеет собственную страничку на вики). + +// Аналогичным образом, шаблонная функция: +template<class T> +void barkThreeTimes(const T& input) +{ + input.bark(); + input.bark(); + input.bark(); +} + +// Обратите внимание, что здесь ничего не указано о типе параметра. Компилятор +// будет генерировать и затем проверять на тип каждый вызов шаблона, поэтому +// данная функция работает с любым типом 'T', который имеет метод 'bark'. + +Dog fluffy; +fluffy.setName("Fluffy"); +barkThreeTimes(fluffy); // Печатает "Fluffy barks" три раза. + +//Параметры шаблона не должны быть классами: +template<int Y> +void printMessage() { + cout << "Learn C++ in " << Y << " minutes!" << endl; +} + +// В конце концов, вы можете явно специализировать шаблоны для более эффективного +// кода. Конечно, большинство реальных случаев использования специализации +// не так тривиально, как это. Обратите внимание, вам все еще нужно явно объявить +// функцию (или класс) в качестве шаблона, даже если вы явно указали все параметры. +template<> +void printMessage<10>() { + cout << "Learn C++ faster in only 10 minutes!" << endl; +} + +printMessage<20>(); // Печатает "Learn C++ in 20 minutes!" +printMessage<10>(); // Печатает "Learn C++ faster in only 10 minutes!" + + +///////////////////// +// Обработка исключений +///////////////////// + +// Стандартная библиотека предоставляет несколько типов исключений +// (смотрите http://en.cppreference.com/w/cpp/error/exception) +// но, в принципе, любой тип может быть брошен в качестве исключения. +#include <exception> +#include <stdexcept> + +// Все исключения, брошенные в блоке _try_ могут быть пойманы в последующем блоке +// _catch_. +try { + // Не выделяйте память в куче для исключений с помощью ключевого слова _new_. + throw std::runtime_error("A problem occurred"); +} + +// Поймайте исключение по константной ссылке, если оно является объектом +catch (const std::exception& ex) +{ + std::cout << ex.what(); +} + +// Ловит любое исключение, не пойманное предыдущим блоком _catch_ +catch (...) +{ + std::cout << "Unknown exception caught"; + throw; // Повторный выброс исключения +} + +/////// +// Получение ресурса есть инициализация (RAII) +/////// + +// Программная идиома объектно-ориентированного программирования, смысл которой +// заключается в том, что с помощью тех или иных программных механизмов получение +// некоторого ресурса неразрывно совмещается с инициализацией, а освобождение - +// с уничтожением объекта. + +// Чтобы понять, на сколько это полезно, +// рассмотрим функцию, которая использует обработчик файлов в С: +void doSomethingWithAFile(const char* filename) +{ + // Для начала, предположим, ничего не может потерпеть неудачу. + + FILE* fh = fopen(filename, "r"); // Открываем файл в режиме чтения. + + doSomethingWithTheFile(fh); + doSomethingElseWithIt(fh); + + fclose(fh); // Закрываем обработчик файла. +} + +// К сожалению, вещи быстро осложняются обработкой ошибок. +// Предположим, fopen может потерпеть неудачу, тогда doSomethingWithTheFile и +// doSomethingElseWithIt вернут коды ошибок, если потерпят неудачу. +// (Исключения являются предпочтительным способом обработки ошибок, +// но некоторые программисты, особенно те, кто имеет большой опыт работы с С, +// не согласны с аргументами о полезности исключений). +// Теперь мы должны проверить каждый вызов на наличие ошибок и закрыть обработчик +// файла, если он есть. +bool doSomethingWithAFile(const char* filename) +{ + FILE* fh = fopen(filename, "r"); // Открывает файл в режиме чтения + if (fh == nullptr) // В случае неудачи возвращаемый указатель принимает значение null. + return false; // Сообщает о неудаче вызывающему. + + // Предположим, каждая функция возвращает false в случае неудачи + if (!doSomethingWithTheFile(fh)) { + fclose(fh); // Закрываем обработчик файла, чтобы не было утечек + return false; // Сообщает об ошибке. + } + if (!doSomethingElseWithIt(fh)) { + fclose(fh); // Закрываем обработчик файла, чтобы не было утечек + return false; // Сообщает об ошибке. + } + + fclose(fh); // Закрываем обработчик файла, чтобы не было утечек + return true; // Указывает на успех +} + +// C-программисты часто упорядочивают это с помощью goto: +bool doSomethingWithAFile(const char* filename) +{ + FILE* fh = fopen(filename, "r"); + if (fh == nullptr) + return false; + + if (!doSomethingWithTheFile(fh)) + goto failure; + + if (!doSomethingElseWithIt(fh)) + goto failure; + + fclose(fh); // Закрываем файл. + return true; // Указывает на успех + +failure: + fclose(fh); + return false; // Сообщает об ошибке. +} + +// Если функции указывают на ошибки с помощью исключений, вещи становятся проще, +// но все еще не оптимальны. +void doSomethingWithAFile(const char* filename) +{ + FILE* fh = fopen(filename, "r"); // Открываем файл в режиме чтения + if (fh == nullptr) + throw std::runtime_error("Could not open the file."); + + try { + doSomethingWithTheFile(fh); + doSomethingElseWithIt(fh); + } + catch (...) { + fclose(fh); // Убедитесь, что закрываете файл, если происходит ошибка. + throw; // Затем повторно бросает исключение. + } + + fclose(fh); // Закрываем файл. + // Успех +} + +// Сравните это с использованием класса потока файла (fstream) в С++, который +// использует свой деструктор, чтобы закрыть файл. Еще раз взгляните выше, +// деструктор вызывается автоматически, когда объект выпадает из области видимости. +void doSomethingWithAFile(const std::string& filename) +{ + // ifstream определяет файловый поток + std::ifstream fh(filename); // Открыть файл + + // Что-то делать с файлом + doSomethingWithTheFile(fh); + doSomethingElseWithIt(fh); + +} // Здесь файл автоматически закрывается в деструкторе. + +// Это имеет _огромнейшие_ преимущества: +// 1. Неважно, что произойдет, +// ресурсы (в данном случае дескриптор файла) будут очищены. +// После того, как вы правильно напишете деструктор, +// Больше будет _невозможно_ закрыть обработчик файлов или допустить утечку. +// 2. Обратите внимание, что код намного проще. +// Деструктор закрывает файловый поток "за кулисами", и вам больше не нужно об +// этом беспокоиться. +// 3. Код устойчив к исключениям. +// Исключение может быть брошено в любом месте в функции, и это никак не повлияет +// на очистку. + +// Весь идиоматический код на С++ широко использует RAII для всех ресурсов. +// Дополнительные примеры включат: +// - Использование памяти unique_ptr и shared_ptr +// - Контейнеры - стандартная библиотека связанных списков, векторы +// (т.е. самоизменяемые массивы), хэш-таблицы и все остальное автоматически +// уничтожается сразу же, когда выходит за пределы области видимости. +// - Ипользование мьютексов lock_guard и unique_lock + +// Контейнеры с пользовательскими классами в качестве ключей требуют +// сравнивающих функций в самом объекте или как указатель на функцию. Примитивы +// имеют компараторы по умолчанию, но вы можете перегрузить их. +class Foo { +public: + int j; + Foo(int a) : j(a) {} +}; +struct compareFunction { + bool operator()(const Foo& a, const Foo& b) const { + return a.j < b.j; + } +}; +// это не допускается (хотя это может варьироваться в зависимости от компилятора) +// std::map<Foo, int> fooMap; +std::map<Foo, int, compareFunction> fooMap; +fooMap[Foo(1)] = 1; +fooMap.find(Foo(1)); //true + +///////////////////// +// Веселые вещи +///////////////////// + +// Аспекты С++, которые могут быть удивительными для новичков (и даже для некоторых +// ветеранов). Этот раздел, к сожалению, очень неполон. С++ является одним из самых +// простых языков, где очень легко выстрелить себе в ногу. + +// Вы можете перегрузить приватные методы! +class Foo { + virtual void bar(); +}; +class FooSub : public Foo { + virtual void bar(); // Перегружает Foo::bar! +}; + + +// 0 == false == NULL (в основном)! +bool* pt = new bool; +*pt = 0; // Устанавливает значение указателя 'pt' в false. +pt = 0; // Устанавливает значение 'pt' в нулевой указатель. Обе строки проходят + // компиляцию без ошибок. + +// nullptr приходит на помощь: +int* pt2 = new int; +*pt2 = nullptr; // Не пройдет компиляцию +pt2 = nullptr; // Устанавливает pt2 в null. + +// Существует исключение для булевых значений. +// Это позволит вам проверить указатели с помощью if(!ptr), +// но как следствие вы можете установить nullptr в bool напрямую! +*pt = nullptr; // Это по прежнему проходит компиляцию, даже если '*pt' - bool! + + +// '=' != '=' != '='! +// Вызывает Foo::Foo(const Foo&) или некий вариант (смотрите "move semantics") +// копирования конструктора. +Foo f2; +Foo f1 = f2; + +// Вызывает Foo::Foo(const Foo&) или вариант, но копирует только часть 'Foo' из +// 'fooSub'. Любые другие члены 'fooSub' пропускаются. Иногда это ужасное поведение +// называют "object slicing." +FooSub fooSub; +Foo f1 = fooSub; + +// Вызывает Foo::operator=(Foo&) или вариант. +Foo f1; +f1 = f2; + + +// Как по-настоящему очистить контейнер: +class Foo { ... }; +vector<Foo> v; +for (int i = 0; i < 10; ++i) + v.push_back(Foo()); + +// В следующей точке размер v устанавливается в 0, но деструктор не вызывается +// и не происходит очистка ресурсов! +v.empty(); +v.push_back(Foo()); // Новые значения копируются в первый вставленный Foo + +// Настоящее уничтожение всех значений v. Смотрите раздел о временном объекте +// для объяснения того, как это работает. +v.swap(vector<Foo>()); + +``` +## Дальнейшее чтение: + +Наиболее полное и обновленное руководство по С++ можно найти на +<http://cppreference.com/w/cpp> + +Дополнительные ресурсы могут быть найдены на <http://cplusplus.com> diff --git a/ru-ru/markdown-ru.html.markdown b/ru-ru/markdown-ru.html.markdown index c41e9676..f71435ea 100644 --- a/ru-ru/markdown-ru.html.markdown +++ b/ru-ru/markdown-ru.html.markdown @@ -2,55 +2,77 @@ language: markdown contributors: - ["Dan Turkel", "http://danturkel.com/"] + - ["Jacob Ward", "http://github.com/JacobCWard/"] +translators: - ["Pirogov Alexey", "http://twitter.com/alex_pir"] + - ["Andre Polykanine", https://github.com/Oire"] filename: markdown-ru.md lang: ru-ru --- Язык разметки Markdown создан Джоном Грубером (англ. John Gruber) -и Аароном Шварцем (англ. Aaron H. Swartz) в 2004 году. +в 2004 году. Авторы задавались целью создать максимально удобочитаемый и удобный в публикации облегчённый язык разметки, пригодный для последующего преобразования в HTML (а также и в другие форматы). +Также реализации Markdown варьируют в зависимости от парсера. +В этом руководстве будет указано, какие функции универсальны для языка, +а какие зависят от конкретного парсера. + +- [HTML-элементы](#html-elements) +- [Заголовки](#headings) +- [Простейшая стилизация текста](#simple-text-styles) +- [Абзацы](#paragraphs) +- [Списки](#lists) +- [Блоки кода](#code-blocks) +- [Горизонтальный разделитель](#horizontal-rule) +- [Ссылки](#links) +- [Изображения](#images) +- [Разное](#miscellany) + +## HTML-элементы +Markdown является надмножеством HTML, поэтому любой HTML-файл является +корректным документом Markdown. + ```markdown -<!-- Markdown является надмножеством HTML, поэтому любой HTML-файл является -валидным документом Markdown, что позволяет использовать напрямую +<!-- Это позволяет использовать напрямую любые элементы HTML-разметки, такие, например, как этот комментарий. Встроенные в документ HTML-элементы не затрагиваются парсером Markdown -и попадают в итоговый HTML без изменений. Однако, следует понимать, +и попадают в итоговый HTML без изменений. Однако следует понимать, что эта же особенность не позволяет использовать разметку Markdown внутри HTML-элементов --> -<!-- Ещё одна особенность формата Markdown состоит в том, что поддерживаемые -возможности разметки зависят от конкретной реализации парсера. В данном -руководстве возможности, поддерживаемые лишь определёнными парсерами, -сопровождаются соответствующими примечаниями. --> - -<!-- Заголовки --> +## Заголовки -<!-- HTML-элементы от <h1> до <h6> размечаются очень просто: +HTML-элементы от <h1> до <h6> размечаются очень просто: текст, который должен стать заголовком, предваряется -соответствующим количеством символов "#": --> +соответствующим количеством символов "#": + +```markdown # Это заголовок h1 ## Это заголовок h2 ### Это заголовок h3 #### Это заголовок h4 ##### Это заголовок h5 ###### Это заголовок h6 +``` +Markdown позволяет размечать заголовки <h1> и <h2> ещё одним способом: -<!-- Markdown позволяет размечать заголовки <h1> и <h2> ещё одним способом: --> +```markdown Это заголовок h1 ================ А это заголовок h2 ------------------ +``` -<!-- Простейшая стилизация текста --> +## Простейшая стилизация текста -<!-- Текст легко сделать полужирным и/или курсивным: --> +Текст легко сделать полужирным и/или курсивным: +```markdown *Этот текст будет выведен курсивом.* _Так же, как этот._ @@ -60,44 +82,58 @@ __И этот тоже.__ ***Полужирный курсив.*** **_И тут!_** *__И даже здесь!__* +``` -<!-- В GitHub Flavored Markdown (версии Markdown, использующейся в GitHub, -для рендеринга Markdown-документов) текст можно сделать зачёркнутым: --> +В Github Flavored Markdown, стандарте, который используется в Github, +текст также можно сделать зачёркнутым: +```markdown ~~Зачёркнутый текст.~~ +``` + +## Абзацы + +Абзацами являются любые строки, следующие друг за другом. +Разделяются же абзацы одной или несколькими пустыми строками: -<!-- Абзацами являются любые строки, следующие друг за другом. -Разделяются же абзацы одной или несколькими пустыми строками: --> +```markdown +Это абзац. Я печатаю в абзаце, разве это не прикольно? -Это абзац. Всё предельно просто. +А тут уже абзац №2. +Эта строка всё ещё относится к абзацу №2! -А тут уже параграф №2. -Эта строка всё ещё относится к параграфу №2! +О, а вот это уже абзац №3! +``` -О, а вот это уже параграф №3! +Для вставки принудительных переносов можно завершить абзац двумя дополнительными пробелами: -<!-- Для вставки принудительных переносов можно использовать HTML-тэг <br/>: --> +```markdown +Эта строка завершается двумя пробелами (выделите, чтобы увидеть!). -Принудительный <br/> перенос! +Над этой строкой есть <br />! +``` -<!-- Цитаты размечаются с помощью символа ">": --> +Цитаты размечаются с помощью символа «>»: +```markdown > Это цитата. В цитатах можно -> принудительно переносить строки, вставляя ">" в начало каждой следующей строки. А можно просто оставлять достаточно длинными, и такие длинные строки будут перенесены автоматически. +> принудительно переносить строки, вставляя «>» в начало каждой следующей строки. А можно просто оставлять их достаточно длинными, и такие длинные строки будут перенесены автоматически. > Разницы между этими двумя подходами к переносу строк нет, коль скоро -> каждая строка начинается с символа ">" +> каждая строка начинается с символа «>» > А ещё цитаты могут быть многоуровневыми: >> как здесь >>> и здесь :) > Неплохо? +``` -<!-- Списки --> -<!-- Маркированные списки размечаются вставкой в начало каждого элемента -одного из символов "*", "+" или "-": -(символ должен быть одним и тем же для всех элементов) --> +## Списки +Маркированные списки размечаются вставкой в начало каждого элемента +одного из символов «*», «+» или «-»: +(символ должен быть одним и тем же для всех элементов) +```markdown * Список, * Размеченный * Звёздочками @@ -113,167 +149,207 @@ __И этот тоже.__ - Список, - Размеченный - Дефисами +``` -<!-- В нумерованных списках каждая строка начинается -с числа и точки вслед за ним: --> +В нумерованных списках каждая строка начинается +с числа и точки вслед за ним: +```markdown 1. Первый элемент 2. Второй элемент 3. Третий элемент +``` -<!-- Заметьте, нумеровать элементы корректно необязательно. Достаточно указать -любое число в начале каждого элемента и рендер пронумерует элементы сам! -Правда, злоупотреблять этим не стоит :) --> +Заметьте, нумеровать элементы корректно необязательно. Достаточно указать +любое число в начале каждого элемента, и парсер пронумерует элементы сам! +Правда, злоупотреблять этим не стоит :) +```markdown 1. Первый элемент 1. Второй элемент 1. Третий элемент -<!-- (Этот список будет отрендерен так же, как и предыдущий!) --> +``` +(Этот список будет отображён так же, как и предыдущий!) -<!-- Списки могут быть вложенными: --> +Списки могут быть вложенными: +```markdown 1. Введение 2. Начало работы 3. Примеры использования * Простые * Сложные 4. Заключение +``` + +Можно даже делать списки задач. Блок ниже создаёт HTML-флажки. -<!-- Блоки с исходным кодом --> -<!-- Фрагменты исходного кода выделяются очень просто - каждая строка блока должна иметь отступ в четыре пробела либо в один символ табуляции --> +```markdown +Для отметки флажка используйте «x» +- [ ] Первая задача +- [ ] Вторая задача +Этот флажок ниже будет отмечен +- [x] Задача была завершена +``` +## Блоки кода + +Фрагменты исходного кода (обычно отмечаемые тегом `<code>`) выделяются просто: +каждая строка блока должна иметь отступ в четыре пробела либо в один символ табуляции. + +```markdown Это код, - причём - многострочный + причём многострочный +``` -<!-- Дополнительные отступы в коде следует делать с помощью четырёх пробелов: --> +Вы также можете делать дополнительные отступы, добавляя символы табуляции +или по четыре пробела: +```markdown my_array.each do |item| puts item end +``` -<!-- Иногда бывает нужно вставить фрагмент кода прямо в строку текста, +Иногда бывает нужно вставить фрагмент кода прямо в строку текста, не выделяя код в блок. Для этого фрагменты кода нужно обрамлять -символами "`": --> +символами «`»: -Например, можно выделить имя функции `go_to()` прямо посреди текста. +```markdown +Ваня даже не знал, что делает функция `go_to()`! +``` -<!-- GitHub Flavored Markdown позволяет указать для блока кода синтаксис оного. -В этом случае синтаксис внутри блока будет подсвечен. Пример: --> +В Github Flavored Markdown для блоков кода можно использовать +специальный синтаксис: -\`\`\`ruby <!-- Только нужно будет убрать символы "\", оставив лишь "```ruby" --> +<pre> +<code class="highlight">```ruby def foobar - puts "Hello world!" + puts "Привет, мир!" end -\`\`\` <!-- И здесь тоже backslashes нужно убрать, т.е. оставить "```" --> +```</code></pre> -<-- Обратите внимание: фрагмент, указанный выше, не предваряется отступами, -поскольку GitHub сам в состоянии определить границы блока - по строкам "```" --> +Во фрагменте, приведённом выше, отступ не требуется. +Кроме того, Github подсветит синтаксис языка, указанного после \`\`\` -<!-- Горизонтальный разделитель (<hr />) --> -<!-- Разделители добавляются вставкой строки из трёх и более -(одинаковых) символов "*" или "-": --> +## Горизонтальный разделитель +Разделители (`<hr>`) добавляются вставкой строки из трёх и более +(одинаковых) символов «*» или «-», с пробелами или без них: + +```markdown *** --- -- - - <!-- между символами допустимы пробелы --> +- - - **************** +``` + +## Ссылки -<!-- Ссылки --> -<!-- Одной из сильных сторон Markdown можно смело считать то, +Одной из сильных сторон Markdown можно смело считать то, как просто размечаются гиперссылки. Для создания ссылки укажите текст ссылки, заключив его в квадратные скобки, -и сразу после - url, заключенный в "круглые" --> +и сразу после — URL-адрес, заключенный в круглые +```markdown [Ссылка!](http://test.com/) +``` +Также для ссылки можно указать всплывающую подсказку (`title`), используя +кавычки внутри круглых скобок: -<!-- Также для ссылки можно указать всплывающую подсказку: --> - +```markdown [Ссылка!](http://test.com/ "Ссылка на Test.com") +``` +Относительные пути тоже возможны: -<!-- В url можно использовать относительные пути: --> - +```markdown [Перейти к музыке](/music/). +``` -<!-- Markdown позволяет размечать ссылку в виде сноски: --> +Markdown также позволяет размечать ссылку в виде сноски: -[Здесь][link1] высможете узнать больше! -А можно кликнуть [сюда][foobar], если очень хочется. +<pre><code class="highlight">[<span class="nv">Щёлкните эту ссылку</span>][<span class="ss">link1</span>] для подробной информации! +[<span class="nv">Также посмотрите эту ссылку,</span>][<span class="ss">foobar</span>] если хотите. -<!-- где-нибудь внизу --> -[link1]: http://test.com/ "Круто!" -[foobar]: http://foobar.biz/ "Тоже хорошо!" +[<span class="nv">link1</span>]: <span class="sx">http://test.com/</span> <span class="nn">"Круто!"</span> +[<span class="nv">foobar</span>]: <span class="sx">http://foobar.biz/</span> <span class="nn">"Нормально!"</span></code></pre> -<!-- Примечания: -- Подсказка может быть заключена в одинарные кавычки вместо двойных, - а также в круглые скобки. -- Сноска может находиться в любом месте документа и может иметь -идентификатор (далее ID) произвольной длины, -лишь бы это ID был уникальным. --> +`Title` также может быть в одинарных кавычках или круглых скобках, а также +отсутствовать вовсе. Ссылки на сноски могут быть в любом месте документа, +а идентификаторы могут быть какими угодно, лишь бы они были уникальными. -<!-- Также при разметке ссылок-сносок можно опустить ID, -если текст ссылки уникален в пределах документа: --> +Существует также неявное именование, когда ссылка является идентификатором. -Ссылка на [Google][]. +<pre><code class="highlight">[<span class="nv">Это</span>][] ссылка. -[google]: http://google.com/ +[<span class="nv">это</span>]: <span class="sx">http://thisisalink.com/</span></code></pre> -<!-- Правда, эта возможность не очень распространена. --> +Правда, эта возможность не очень распространена. -<!-- Изображения --> -<!-- Разметка изображений очень похожа на разметку ссылок. -Нужно всего лишь добавить "!" перед ссылкой! --> +## Изображения +Разметка изображений очень похожа на разметку ссылок. +Нужно всего лишь добавить перед ссылкой восклицательный знак! +```markdown  +``` +Изображения тоже могут быть оформлены, как сноски. -<!-- Изображения тоже могут быть оформлены, как сноски: --> - -![Альтернативный текст][myimage] - -![То же изображение ещё раз][myimage] - -[myimage]: relative/urls/cool/image.jpg "подсказка" +<pre><code class="highlight">![<span class="nv">Это альтернативный текст.</span>][<span class="ss">myimage</span>] -<!-- Ещё немного ссылок: --> -<!-- Автоссылки --> +[<span class="nv">myimage</span>]: <span class="sx">relative/urls/cool/image.jpg</span> <span class="nn">"Если нужна подсказка, её можно добавить"</span></code></pre> +## Разное +### Автоссылки +```markdown Ссылка вида <http://testwebsite.com/> эквивалентна [http://testwebsite.com/](http://testwebsite.com/) +``` -<!-- Автоссылки для адресов электронной почты --> +### Автоссылки для адресов электронной почты +```markdown <foo@bar.com> +``` + +### Экранирование символов -<!-- Экранирование символов --> +```markdown +Я хочу напечатать *текст, заключённый в звёздочки*, но я не хочу, +чтобы он был курсивным. Тогда я делаю так: +\*Текст, заключённый в звёздочки\* +``` -<!-- Может потребоваться вставить спецсимвол в текст "как есть", -т.е. защитить его от обработки парсером. -Такой символ должен быть "экранирован" с помощью обратной косой черты -(символа "\"): --> +### Клавиши на клавиатуре +В Github Flavored Markdown для представления клавиш на клавиатуре +вы можете использовать тег `<kbd>`. -\*текст, заключённый в звёздочки!\* +```markdown +Ваш компьютер завис? Попробуйте нажать +<kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Del</kbd> +``` -<!-- Таблицы --> -<!-- Таблицы официально поддерживаются только в GitHub Flavored Markdown, +### Таблицы +Таблицы официально поддерживаются только в GitHub Flavored Markdown, да и синтаксис имеют не слишком удобный. -Но если очень нужно, размечайте таблицы так: --> +Но если очень нужно, размечайте таблицы так: +```markdown | Столбец 1 | Столбец 2 | Столбец 3 | | :----------- | :----------: | -----------: | | Выравнивание | Выравнивание | Выравнивание | | влево | по центру | вправо | +``` +Или более компактно -<!-- Или более компактно --> - -Колонка 1|Колонка 2|Колонка 3 +```markdown +Столбец 1|Столбец 2|Столбец 3 :--|:-:|--: Выглядит|это|страшновато... - -<!-- Ну вот и всё! --> - ``` -За более подробной информацией обращайтесь к [статье](http://daringfireball.net/projects/markdown/syntax) Джона Грубера о синтаксисе Markdown. +Ну вот и всё! -Также часто бывает полезной отличная ["шпаргалка"](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) по Markdown от Adam Pritchard. +За более подробной информацией обращайтесь к [статье](http://daringfireball.net/projects/markdown/syntax) Джона Грубера о синтаксисе Markdown. -Если вдруг встретите ошибки в переводе или же захотите его дополнить, делайте pull requests - авторы всегда рады обратной связи! +Также часто бывает полезной отличная ["шпаргалка"](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) по Markdown от Адама Притчарда. diff --git a/ru-ru/php-ru.html.markdown b/ru-ru/php-ru.html.markdown index d17f24fc..42c4d360 100644 --- a/ru-ru/php-ru.html.markdown +++ b/ru-ru/php-ru.html.markdown @@ -451,7 +451,7 @@ $value = include 'my-include.php'; class MyClass { - const MY_CONST = 'value'; // A constant + const MY_CONST = 'value'; // Константа static $staticVar = 'static'; |