Ответы 2009 вариант 3 (1119607)
Текст из файла
Вариант 3_2009 Ф.И.О.___________________________________№ группы________
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
1. Есть ли ошибки в приведенном фрагменте программы на С++? Если есть, то объясните, в чем они заключаются. Ошибочные конструкции вычеркнуть из текста программы. Что будет выдано в стандартный поток вывода при работе программы?
class T {
public: virtual void f (int x) { h (); cout << "T::f," << x << endl; }
void g () { h (); cout << "T::g" << endl; }
virtual void h () { cout << "T::h" << endl; }
};
class U: virtual public T {
public: void f (int y) { h (y); cout << "U::f," << y << endl; }
virtual void g () { h (0); cout << "U::g" << endl; }
void h (int k) { cout << "U::h," << k << endl; }
};
int main( ){ T t; U u; T * p = & u;
p -> f (1); p -> g (); p -> h (); p -> h (2); }
Ответ: Ошибочным является вызов p -> h(2) (Функция h(int) из производного класса не замещает h() базового класса, так как имеет отличающийся набор параметров).
Будет выдано в поток: U::h,1 U::f,1 T::h T::g T::h
Критерии: За каждую не найденную ошибку, лишнюю ошибку или неправильно вызванную функцию – 2.
2. Есть ли ошибки в реализации функций B::g() и main()? Если есть, исправьте неверные операторы из этой функции, используя операцию разрешения области видимости "::".Для всех операторов этих функций укажите, из какой области видимости вызываются используемые в них функций f() и g().
int x = 0;
int f () { return x = 1; }
class A { int x;
public:A ( int n = 2) { x = n; }
int f () { return x = 3; }
int f (int a, int b) { return x = a % b; } };
class B: public A { int x;
public: int f (int a) { return x = a; }
int f (int a, int b) { return x = a + b; }
int g (A * a, B * b); };
int B::g (A * pa, B * pb)
{ x = f ();
x = f (5);
x = f (6, 6);
x = A:: f (5);
return -1; }
int main ()
{ B a; x = a.f ();
x = a.f (7);
return a.g (& a, & a); }
Ответ: x = A:: f (); // A::f ()
x = B:: f (5); // B::f (5)
x = B:: f (6, 6); // B::f (6, 6)
x = B:: f (5); // B::f (5)
x = a.A:: f (); // A::f ()
x = a.B:: f (7); // B::f (7)
return a.B::g (& a, & a);
Отмечены исправляющие (обязательные) изменения.
Критерии: За каждое не отмеченное уточнение области видимости (из 7) -2. За каждое не найденное исправление (из 3) еще -3.
3. Привести по одному примеру перегрузки бинарной, унарной префиксной и постфиксной операций (всего 3 примера). Указать особенности перегрузки операций присваивания. Можно ли изменить приоритет операции при её перегрузке?
Ответ: 1. Бинарная операция (сложение и присваивание):
Друг: complex & operator+= (complex & a, const complex & b)
{ a.re += b.re; a.im += b.im; return a; }
Метод: complex & complex::operator+= (const complex & a)
{ re += a.re, im += a.im; return * this; }
2. Унарная префиксная операция:
Друг: complex & operator++ (complex & a)
{ ++ a.re; return a; }
Метод: complex & complex::operator++ ()
{ ++ re; return * this; }
3. Унарная постфиксная операция:
Друг: complex operator++ (complex & a, int b)
{ complex temp = a; ++ a.re; ++ a.im; return temp; }
Метод: complex complex::operator++ (int b)
{ complex temp = * this; ++ re; ++ im; return temp; }
4. Операции присваивания могут перегружаться только нестатическими членами классов, но не функциями-друзьями.
5. При перегрузке операций не могут меняться их основные свойства – количество необходимых операндов, ассоциативность и приоритет.
Критерий: За отсутствие каждого из примеров: -1. За отсутствие описания особенностей операции присваивания: -2. Неправильный ответ на вопрос о свойствах операций: -2. На последний вопрос лаконичный ответ «нет» засчитывается как правильный.
4. Для класса комплексных чисел template<class T> class complex { T r; T i; ... };
написать два варианта реализации префиксной операции увеличения "++", выполняющей увеличение на 1 действительной части комплексного числа методом класса и функцией-другом класса.
Ответ: template<class T> & complex<T> complex<T>::operator++ ()
{ ++ r; return * this; }
template<class T> & complex<T> operator++ (complex<T>& x)
{ ++ x.r; return x; }
Критерий: За отсутствие каждого примера или ошибки в нем: -5.
5. Данные каких типов могут подвергаться динамическому и статическому приведению? В чём проявляется отличие выполнения динамического приведения типов для указателей и ссылок? Какие свойства указателей и ссылок влияют на это отличие? Приведите примеры фрагментов программы с использованием подобных операций.
Ответ: Динамическое и статическое приведение типов возможно для объектов родственных полиморфных классов, относящихся к одной иерархии классов. Статическое приведение возможно также для свободных указателей (void *), которые могут преобразовываться в значения любых типов указателей, и для преобразований между арифметическими типами (отсутствие этого добавления не наказывается). Указатель может иметь нулевое значение, поэтому при динамическом приведении указателя в случае возникновения ошибки может возвращаться это нулевое значение, которое затем может быть проверено в программе. Ошибка при приведении ссылки всегда приводит к возбуждению исключительной ситуации bad_cast, так как никакого выделенного значения для ссылок не существует. Проверка правильности динамического приведения ссылок всегда выполняется перехватом исключительной ситуации.
Пример: class A { ... };
class B: public A { ... };
class C: public A { ... };
void f (A * p, A & r)
{ if (B * pp = dynamic_cast<B *> (p))
{ ... /* использование указателя pp */ }
else { ... /* указатель pp не принадлежит нужному типу */ }
B & pr = dynamic_cast<B &> (r); ... /* использование ссылки pr */ }
void g ()
{ try { f (new B, * new B); // правильный вызов
f (new C, * new C); // выход в перехватчик (C – из другой
// иерархии, основанной на том же
// базовом классе)
}
catch (bad_cast)
{ ... // обработка исключительной ситуации
}
}
Критерий: За неверное понимание сути операций приведения типов: -4. За неверное понимание приведения типа в одном из случаев: -4. За неверное понимание сути динамического приведения типа и для указателей и для ссылок: -6. Отсутствие одного из примеров (здесь приведен обобщенный пример, эквивалентный сразу двум простым) при демонстрации правильного понимания сути: -2.
6. Написать функцию g() с тремя параметрами: непустой и неизменяемый контейнер-вектор типа vector<double>, непустой контейнер-список типа list<double>, целое число – шаг по первому контейнеру. Функция должна сравнивать элементы списка, выбираемыми от его начала с шагом, равным 1, с элементами вектора, выбираемыми от начала с шагом, равным третьему параметру. Если обнаруживается несовпадение очередной выбранной пары, то в список в текущем месте вставляется отсутствующий элемент. Изменённый список распечатывается в обратном порядке. Функция возвращает количество элементов, вставленных в список.
Решение: typedef vector<double> V;
typedef list<double> L;
int g (const V & vect, L & lst, int step)
{ V:: const_iterator vp = vect.begin ();
L:: iterator lp = lst.begin (); int t = 0;
do { if (* lp != * vp) lst.insert (lp, * vp), ++ t;
if (vect.end() - vp <= step) break;
++lp; vp += step;
} while (lp != lst.end ());
L:: reverse_iterator rp = lst.rbegin ();
while (rp != lst.rend ())
{ cout << * rp << ' '; ++ rp; }
cout << endl; return t;
}
Критерий: За каждую существенную ошибку: -3. Если проверка на выход за границу вектора проводится в другом месте (например, в постусловии цикла) – не наказывать.
7. Для объектов из задания 2 определить, тела каких конструкторов и деструкторов (возможно пустые, если они не определены явно) и в каком порядке будут исполнены при работе следующего фрагмента программы:
int main () { A a; class C { B b; A a; public: C (): b(), a (b) {} }; C c; }
Ответ: A (), A (), B (), A (A &), C (), ~C (), ~A (), ~B (), ~A (), ~A ().
Критерии: За каждую ошибку –3.
8. Описать прототипы двух перегруженных функций f() из некоторой области видимости, для которых будут верны следующие обращения к ним:
f (1000000000000); f (1); f (); f (0, 0); f ("t"); f (1, "u");
Ответ: void f (double d = 0, const char * s = 0);
// long int и float засчитывать за правильное
void f (const char *); либо void f (const char *, int i = 0);
Критерии: За каждую ошибку –5. Если приводятся более, чем две функции –10. Пропуск слова const в обеих функциях одновременно считать за одну ошибку.
9. Есть ли синтаксические ошибки в тексте приведенной программы? Если можно исправить описание класса, не вводя дополнительных членов, чтобы программа стала верной, то как?
class A { static int i;
void f () const { if (i < 0) g (i);
cout << "f ()" << endl; }
void g (int & n) { i = n; f (); cout << "g ()" << endl; }
};
int A::i = 1;
int main () { const A a; a.g (2); }
Ответ: 1. Заменить слово “class” словом “struct”, либо вставить после открывающей фигурной скобки определения класса слово “public:”.
2. В определении метода “g()” вставить перед типом формального параметра слово “const”.
3. В определении метода “g()” вставить после списка формальных параметров слово “const”.
Критерий: За пропуск ошибок доступа к закрытым членам класса: -5. За пропуск одной ошибки вызова метода “g()”: -5. За пропуск обеих таких ошибок: -8. За указание ошибки там, где ее нет: -5.
10. Что будет выдано в стандартный канал вывода при работе следующей программы?
struct X; void f(X & x, int n);
int const P = 1; int const Q = 1; int const R = 1;
struct X { X() { try { f(*this, -1); cout << 1 << endl; }
catch (X) { cout << 2 << endl; }
catch (int) { cout << 3 << endl; }
}
X (X &) { cout << 4 << endl; }
~X () { cout << 5 << endl; }
};
struct Y: X { Y () { f(*this, 1);
cout << 6 << endl; }
Y (Y &) { cout << 7 << endl; }
~Y () { cout << 8 << endl; }
};
void f(X & x, int n) { try { if (n < 0) throw x;
if (n > 0) throw 1;
cout << 9 << endl;
}
catch (int) { cout << 10 << endl; }
catch (X& a) { cout << 11 << endl;
f(a, 0);
cout << 12 << endl;
throw;
}
}
int main() { try { Y a; }
catch (...) { cout << 13 << endl;
return 0;
}
cout << 14 << endl;
return 0;
}
Ответ: 4 11 9 12 2 5 10 6 8 5 14
Критерии: За каждую неверную (лишнюю или пропущенную) печать -2.
Характеристики
Тип файла документ
Документы такого типа открываются такими программами, как Microsoft Office Word на компьютерах Windows, Apple Pages на компьютерах Mac, Open Office - бесплатная альтернатива на различных платформах, в том числе Linux. Наиболее простым и современным решением будут Google документы, так как открываются онлайн без скачивания прямо в браузере на любой платформе. Существуют российские качественные аналоги, например от Яндекса.
Будьте внимательны на мобильных устройствах, так как там используются упрощённый функционал даже в официальном приложении от Microsoft, поэтому для просмотра скачивайте PDF-версию. А если нужно редактировать файл, то используйте оригинальный файл.
Файлы такого типа обычно разбиты на страницы, а текст может быть форматированным (жирный, курсив, выбор шрифта, таблицы и т.п.), а также в него можно добавлять изображения. Формат идеально подходит для рефератов, докладов и РПЗ курсовых проектов, которые необходимо распечатать. Кстати перед печатью также сохраняйте файл в PDF, так как принтер может начудить со шрифтами.