II Flashcards

1
Q

Операторы “.”, “→”, ключевое слово this

A
  • как обратиться к полю (аналогично к методу):

объект.поле

  • стрелочка это то же самое, но не для самих объектов, а указателей для них

(*p).f( ); или же p -> f( );

  • this это указатель на тот объект, в котором мы “сейчас” находимся

Пример:

class String {

public:

String (const char* str, int size) {

this str -> new char [size];

….

}

~String () {delete [] this str}

private:

char* str;

int size;

}

};

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Оператор присваивания

A
  • оператор присваивания нужно определять “руками” так как по умолчанию оператор просто копирует поля
  • это метод, возвращает ссылку на класс на котором его определяют

String& operator = (const String& s) {

if (&s == this) return *this; // проверка, что объект не равен самому себе

delete[] str;

str = new char [s.size];

for ( … ) {…};

return *this;

}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Правило трех (the rule of three)

A

Эмпирическое/эвристическое правило, которое говорит, что если класс требует определения одного из трех (хотя бы одного из трех):

  1. Конструктора копировани
  2. Оператора присваивания
  3. Деструктора

То значит он требует определения всех этих вещей (иначе крах)

В С++11 вместо “Правила трех появилось “Правило пяти”

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Списки инициализации в конструкторах

A
  • Как в конструкторе инициализировать поля, которые нельзя изменять внутри тела конструктора? Для этого существуют списки инициализации в конструкторах.

int z = 10;

Class C {

const int x = 3;

int& y = z;

C (const int x, int& y) : x (x); y (y) {} // название поля (значение, которым его надо проинициализировать)

}

};

  • ! Поля инициализируются ДО входа в тело конструктора
  • Лучше всегда пользоваться списками инициализации, а не обычным присваиванием (эффективнее с точки зрения управления памятью)
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Ключевое слово explicit

A

String s = s1 + ‘a’; // a имеет тип char и сложение строки с ним не определено

  • Можно из типа char сделать строку и потом производить действия
  • Неявная конверсия в int даст некорректный результат, поэтому конверсию нужно делать в явном виде. Поэтому возникает желание запретить неявные преобразования типов - для этого существует ключевое слово explicit, которое пишется перед конструктором

explicit String (int size) { … }

  • Если это не конструктор копирования, то рекомендуется везде делать explicit конструкторы
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Константные методы

A

Пусть есть метод в конструкторе int size () {return size_;}

  • По умолчанию считается, что каждый метод класса имеет право менять поля этого класса

сonst String s =”abc”;

s. size (); // вызовет ошибку компиляции так как метод size потенциально может менять поля, которые мы задали как неизменяемые (константы)
* чтобы метод класса можно было вызывать над константным объектом нужно явно пометить, что он не меняет поля класса, то есть допускает вызов от константного объекта.

Что нужно сделать:

int size () const {return size_;}

  • сам метод является константным по отношению к объекту, которым вызывается. Вот тогда можно будет этот метод вызывать от константных объектов, но все поля внутри этого метода считаются константными (то есть нельзя из этого метода вызвать модифицирующие операции над полями объектов)
  • жизненный метод, нужно не забывать ставить метку там, где это нужно
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Ключевое слово mutable

A
  • допустим есть объект, который служит для логирования и в нём есть поле, в котором считается, сколько раз методы были вызваны - при каждом вызове некоторого метода счетчик увеличивается на 1
  • проблема: допустим мы создали константный объект и у него начинаем вызывать методы, но это затруднительно, так как поля не могут меняться (но мы хотим менять одно конкретное поле)
  • для этого есть специальное ключевое слово, которое разрешает менять отдельные поля в константном методе (mutable)

определяем поле класса следующим образом:

mutable int x;

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Ключевое слово friend

A
  • Допустим имеется класс и в нём есть некоторое внутреннее приватное представление, а вы хотите определить оператор ввода этого в поток (cin)
  • Проблема: вы не можете этого сделать, так как поля приватные и их нельзя трогать извне, а оператор ввода в поток вы не можете определить внутри класса как член (потому что у него левый операнд это поток, а внутри класса вы можете определять только те операторы, у которых левый операнд это объект вашего класса)
  • Таким образом, нужен оператор, который не является членом класса, но может иметь допступ к его приватным полям (исключительный). Для этого есть ключевой слово friend, которое ставится перед оператором

friend f ( … )

  • не рекомендуется делать много друзей - нарушается принцип инкапсуляции
  • друзьями можно объявлять целые классы, это будет означать, что все методы одного класса имеют доступ к приватной части другого класса
  • друзья не взаимны (если А это друг Б, то обратное может быть не верно)
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Делегирующие конструкторы

A
  • пишем конструктор класса String от двух параметров: String (const char* str, int size) и вы хотите написать другой конструктор, который делает всё то же самое, что и первый, но кроме этого еще что-то делает (доп параметры)
  • Проблема: не хочется переписывать наполнение старого конструктора
  • Допустим мы хотим написать конструктор, в котором переменные принимаются в обратном порядке (int, const chat*). Для этого применяются делегирующие конструкторы (появились в C++11).

String (int size, const chat* str) : String (str, size) { };

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Ключевое слово static

A
  • представьте, что у вас есть класс в котором помимо прочего хранится какая-то информация (например, сколько было создано объектов этого класса и существует сейчас). То есть должно быть в классе поле про сам класс, которое не принадлежит ни одному объекту. Для этого некоторое поле класса можно объявить static

static int x;

  • это поле будет видимо для всех объектов (на общих основаниях)
  • static может быть не только в классе, но и в функциях
  • переменные static удалятся после завершения программы
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q
A
  • представьте, что у вас есть класс в котором помимо прочего хранится какая-то информация (например, сколько было создано объектов этого класса и существует сейчас). То есть должно быть в классе поле про сам класс, которое не принадлежит ни одному объекту. Для этого некоторое поле класса можно объявить static

static int x;

  • это поле будет видимо для всех объектов (на общих основаниях)
  • static может быть не только в классе, но и в функциях
  • переменные static удалятся после завершения программы
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Указатели на члены

A

class C {public: int a; char b;}

  • Пусть есть класс с некоторыми полями и вы хотите объявить указатель не на сам объект типа C, а на некоторое поле этого объекта

int main ( ) {

int C::* p = &C::a;

C c;

c.*p = 5; // можно менять значение параметра а

}

  • аналогично можно вызывать методы класса
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Перегрузка операторов, арифметические операторы

A
  • пусть есть класс BigInteger - сколько угодно большое число, записанное в виде массивов и мы хотим определить операции над ним

Сложение:

BigInteger operator + (const BigInteger& x) const { // этот оператор возвращает некоторый новый объект, не меняя старый, поэтому нужно добавить константный метод

// const BigInteger& мы пишем для того, чтобы каждый раз не создавалась лишняя копия BigInteger

BigInteger sum = * this;

return sum += x;

}

Оператор += :

BigInteger& operator += (const BigInteger& x) {

}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Операция И и ИЛИ

A
  • Логическая операция И выполняется с помощью оператора &&.
  • Логическая операция ИЛИ выполняется с помощью оператора | | .
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Синтаксис цикла for

A

Синтаксис цикла for таков:

for (Выражение инициализации, выполняемое только р а з ;
Условие выхода, проверяемое в начале каждой итерации;
Выражение цикла, выполняемое в конце каждой итерации)
{
Блок инструкций;
}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Синтаксис цикла while

A

Синтаксис этого цикла имеет следующий вид:

whilе (Выражение)
{
// Если Выражение == true
Блок_Инструкций;
}

17
Q

Основные этапы создания приложений C++

A

Основные этапы создания приложений C++ приведены ниже.

  1. Написание (программирование) кода C++ с использованием текстового редак­тора.
  2. Компиляция кода с помощью компилятора C++, который преобразовывает ис­ходный текст в команды машинного языка и записывает их в объектный файл (object file).
  3. Компоновка результатов работы компилятора с помощью компоновщика и по­ лучение окончательного выполнимого файла (.ехе в Windows, например).

Компиляция (compilation) представляет собой этап, на котором код C++, содержа­щийся обычно в текстовых файлах с расширением . срр, преобразуется в бинарный код, который может быть выполнен процессором. Компилятор (compiler) преобразует по одному файлу кода за раз, создавая объектный файл с расширением .о или .obj и игнорируя связи, которые код в этом файле может иметь с кодом в другом файле.

Распознавание этих связей и объединение кода в одно целое является задачей ком­поновщика (linker). Кроме объединения различных объектных файлов, он разрешает имеющиеся связи и в случае успешной компоновки создает выполнимый файл, который можно выполнять и в конечном счете распространять среди пользователей. Весь процесс в целом называется построением выполнимого файла.

В дополнение к перечислен­ ным выше трем этапам (программирование, компиляция и компоновка) разработка зачастую подразумевает этап отладки (debugging), на котором программист анали­зирует ошибки в приложении и исправляет их.

18
Q

IDE

A

Большинство программистов предпочитают использовать интегрированную сре­ду разработки (Integrated Development Environment — IDE), объединяющую этапы программирования, компиляции и компоновки в пределах единого пользовательского интерфейса, предоставляющего также средства отладки, облегчающие обнаружение ошибок и устранение проблем.

19
Q

Директива препроцессора #include

A

include “…путь к файлу FileA\FileA”

Как и предполагает его название, препроцессор (preprocessor) — это инструмент, запускающийся перед фактическим началом компиляции.

Директивы препроцессора (preprocessor directive) — это команды препроцессору, которые всегда начинаются со
знака “диез” (#).

В профессиональных приложениях C++ включаются не только стандартные заголовочные файлы, но и разработанные программистом. Сложные прило­жения, как правило, состоят из нескольких исходных файлов, причем одни из них должны включать другие. Так, если некоторый объект, объявленный в файле FileA, должен использоваться в файле FileB, то первый файл необходимо включить в последний. Обычно для этого в файл FileB помещают директиву #include:

При включении самодельного заголовочного файла мы используем кавыч­ки, а не угловые скобки. Угловые скобки ( о ) обычно используются при включении стандартных заголовочных файлов.

20
Q

Функция main( ) и аргументы командной строки, оператор вывода в поток, строковый литерал

A

Выполнение программ на языке C++ всегда начинается с функции main ( ). Согласно стандарту перед функцией main ( ) указывается тип int.

Во многих приложениях C++ можно найти вариант функции main ( ), выглядящий следующим образом:

int main( int argc, char* argv [])

Это объявление совместимо со стандартом и вполне приемлемо, поскольку функция main ( ) возвращает тип int, а содержимое круглых скобок - это аргументы (argument), передаваемые программе. Такая программа позво­ляет пользователю запускать ее с аргументами командной строки, например как:

program.exe /DoSomethingSpecific

/DoSomethingSpecific - это аргумент данной программы, передаваемый операционной системой в качестве параметра для обработки в функции main ( ).

cout — это по­ток, определенный в пространстве имен std (поэтому и std : : cout), а то, что мы делаем, — это помещение текстовой строки Hello World в данный поток с использованием оператора вывода (или вставки) в поток <<.

Оператор вывода в поток (stream insertion operator) ис­пользуется каждый раз, когда в поток нужно вывести новый элемент.

Преимущество потоков C++ заключается в одинаковой семантике, используемой потоками разного типа. В результате различные операции, осуществляемые с одним и тем же текстом, например вывод в файл, а не на консоль, выглядят одинаково и ис­пользуют один и тот же оператор << , только для std : : fstream вместо std : :cout.

Фактический текст, заключенный в кавычки (“Hello World”), называет­ся строковым литералом (string literal).

21
Q

Возврат значения функцией main ( )

A

main () — это функция, всегда и обязательно возвращающая целое число.

Это целочисленное значение возвращается операционной системе и, в зависимости от характера вашего приложения, может быть очень полезным, поскольку большинство операционных систем предусматривает для других приложений возможность обра­
титься к возвращенному значению.

Не так уж и редко одно приложение запускает другое, и родительскому приложению (запустившему дочернее) желательно знать, закончило ли дочернее приложение свою задачу успешно. Программист может ис­пользовать возвращаемое значение функции main ( ) для передачи родительскому приложению сообщения об успехе или неудаче.

22
Q

Чувствительность языка С++ к регистру

A

Язык C++ чувствителен к регистру

23
Q

Использование ключевого слова using

A

Многие программисты находят утомительным регулярный ввод при наборе исхо­дного текста спецификатора std при использовании имени cout и других подобных средств, содержащихся в том же пространстве имен. Объявление using namespace, позволит избежать этого повторения.

24
Q

Комментарии в коде

A

■ Символ / / означает, что следующая далее строка — комментарий. Например:
/ / Это комментарий

■ Текст, содержащийся между символами /* и * /, также является комментарием, даже если он занимает несколько строк:

/* Это комментарий,
занимающий две строки * /

25
Q

Применение потока cin

A

Применение потока cin очень простое; он работает в паре с переменной, в которую следует поместить вводимые данные:

std : : cin >> Переменная;

Таким образом, за потоком cin следуют оператор извлечения значения >> (данные извлекаются из входного потока) и переменная, в которую следует поместить считы­ваемые данные. Если вводимые данные разделены пробелом, и их следует сохранить в двух разных переменных, можно использовать цепочку операторов:

std : : cin >> Переменная1 >> Переменная2;

Обратите внимание на то, что поток cin применяется для ввода как текстовых, так и числовых данных.