Ответы на некоторые вопросы по С++ (2 стр)
Автор: PP
41. Как проинициализировать динамическую переменную?
A * a = new A(...);
Либо placement new:
A * a = new(ptr_on_block_in_mem) ( arguments to constructor);
42. Как объявить константу в классе? Можно ли объявить дробную константу?
Вторая часть вопроса - Да.
struct A { const int a; A() : a(10) {} };
struct A { static const int a = 10; }; // only const static integral data members can be initialized inside a class or struct
struct A { static const int a; }; A::a = 10;
struct A { static const double a; }; A::a = 10.;
43. Каким образом разрешается инициализировать константные поля в классе?
В списке инициализации. Для static - см 42. При этом, в каждом конструкторе. Замечание: умалчиваемые конструкторы
перестают быть доступны. То же касаетя ссылок как полей.
44. В каком порядке инициализируются поля в классе? Совпадает ли этот порядок с порядком перечисления инициализаторов в списке инициализации конструктора?
В порядке их объявления. Нет.
45. Какие конструкции С++ разрешается использовать в списке инициализации качестве инициализирующих выражений?
??? Отмечаем порядок. Такое недопустимо:
class A { int* a; int* b; A(): b( new int( )), a( b) { } };
При выполнении конструктора-деструктора вызовы виртуальных функции не
виртуальны.
46. Какой вид конструктора фактически является конструктором преобразования типов?
не explicit конструктор с одним аргументом (конструктор инициализации).
47. Для чего нужны функции преобразования? Как объявить такую функцию в классе?
Вроде бы это всегда называлось не "функция преобразования", а "оператор приведения типа".
Преобразовывать тип к другому. struct A { operator C () {...}; operator B () const {...}; };
48. Как запретить неявное преобразование типа, выполняемое конструктором инициализации?
Перед соответствующим конструктором написать explicit: struct A { explicit A(int) {} };
49. Какие проблемы могут возникнуть при определении функций преобразования?
??? (видимо нежелательные/сложнопредсказуемые/неожиданные приведения типов)
50. Для чего служит ключевое слово explicit?
см 48.
51. Влияет ли наличие целочисленных констант-полей на размер класса?
Да. (ессно если не static)
52. Разрешается ли объявлять массив в качестве поля класса. Как присвоить элементам массива начальные значения?
Да.
int a[2] = {1, 2}; В классе - никак (за исключением 55).
53. Сколько операндов имеет операция индексирования []? Какой вид результата должна возвращать эта операция?
Один. Любой.
54. Для чего нужны статические поля в классе? Как они определяются?
Статические поля - переменные класса (нестатические поля - переменные объекта).
Определяются - вне класса (за исключением 42 (initialized const static integral data members)):
struct A { static int a; }; int A::a;
55. Как объявить в классе и проинициализировать статический константный массив?
struct A { static const int a[2]; }; const int A::a[2] = {1, 2};
56. Что такое выравнивание и от чего оно зависит? Влияет ли выравнивание на размер класса?
Implementation defined. Да.
57. Дайте определение контейнера.
Containers are objects that store other objects. (см стандарт 2003: стр 465)
58. Какие виды встроенных контейнеров в С++ вы знаете?
Sequences : vector, list, deque, queue, stack
Associative containers : map, set, multimap, multiset
Other : priority_queue, bitset
59. Какие виды доступа к элементам контейнера вам известны?
Разыменование итератора, оператор индексирования.
60. Чем отличается прямой доступ от ассоциативного?
???
61. Перечислите операции, которые обычно реализуются для последовательного доступа к элементам контейнера.
begin, end, инкремент итератора
62. Дайте определение итератора.
TODO: from GD
63. Можно ли реализовать последовательный доступ без итератора? В чем преимущества реализации последовательного доступа с помощью итератора?
Да. Единообразная работа с различными сущностями.
64. Что играет роль итератора для массивов С++?
Указатель.
65. Что такое деструктор? Может ли деструктор иметь параметры?
Нет.
66. Почему для классов-контейнеров деструктор надо писать явным образом?
да вроде незачем :) или я чего-то не знаю :(
У стандартных классов-контейнеров в стандарте прописано, что должен быть деструктор.
67. Допускается ли перегрузка деструкторов?
Нет.
68. Что такое «глубокое копирование» и когда в нем возникает необходимость?
Когда при копировании указателя нужно скопировать объект на который он указывает.
69. Какое копирование осуществляет стандартный конструктор копирования?
Вызывает конструкторы копирования баз и членов.
70. Чем отличается копирование от присваивания?
Это разные операции :)
Копирование - создание одного объекта по другому (с помощью конструктора копирования).
Присваивание - изменение содержимого существующего объекта (присваиванием в него содержимого другого объекта).
71. Объясните, почему в операции присваивания требуется проверка присваивания самому себе?
Необязательно, например каноническая реализация через swap и конструктор копирования этой проверки не осуществляет (см. 31).
72. Можно ли в качестве операции индексирования использовать операцию вызова функции ()? В чем ее преимущества перед операцией []?
Можно, ей можно передавать нескольео аргументов.
73. Почему необходимо писать два определения операции индексирования? Чем они отличаются?
Отличаются наличием const, обычно нужны для того, чтобы была возможность изменять содержимое не const контейнера,
и при этом иметь доступ к элементам const контейнера:
struct A
{
T& operator[] (int);
const T& operator[] (int) const;
};
74. Дайте определение вложенного класса.
struct A { struct NestedClass {}; };
75. Можно ли класс-итератор реализовать как внешний класс? А как вложенный? В чем отличия этих методов реализации?
Да. Да. ???.
76. Может ли объемлющий класс иметь неограниченный доступ к элементам вложенного класса? А вложенный класс — к элементам объемлющего?
Да (если я правильно понял вопрос :) ).
77. Ограничена ли глубина вложенности классов?
Нет.
78. Можно ли определить вложенный класс внешним образом? Зачем это может понадобиться?
struct A { struct NestedClass; }; struct A::NestedClass {};
Если NestedClass нуждается в определении класса в который он вложен.
79. Каким образом вложенный класс может использовать методы объемлющего класса? А объемлющий — методы вложенного?
Каким угодно. (???)
80. Что такое «запредельный» элемент, какую роль он играет в контейнерах?
end() - Элемент следующий за последним. Используется в условии окончании перебора элементов (и соответственно возвращается при неудачном поиске в контейнере и аналогичных ситуациях).
81. Объясните, по каким причинам трудно написать универсальный контейнер, элементы которого могут иметь произвольный тип.
Из-за строгой типизации (нужен либо VARIANT, либо dynamic_cast).
28 июля 2006 (Обновление: 13 янв 2009)