Ответы 2009 вариант 1 (Коллоквиум. Варианты заданий и ответы)
Описание файла
Файл "Ответы 2009 вариант 1" внутри архива находится в папке "Коллоквиум. Варианты заданий и ответы". Документ из архива "Коллоквиум. Варианты заданий и ответы", который расположен в категории "". Всё это находится в предмете "практикум (прикладное программное обеспечение и системы программирования)" из 4 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Онлайн просмотр документа "Ответы 2009 вариант 1"
Текст из документа "Ответы 2009 вариант 1"
Вариант 1_2009 Ф.И.О.___________________________________№ группы________
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
1. Есть ли ошибки в реализации функций C::g() и main()? Если есть, исправьте найденные ошибки, используя операцию разрешения области видимости "::". Для всех операторов этих функций, используя операцию разрешения области видимости "::", также укажите, из какой области видимости выбираются участвующие в их записи имена.
int x = 0;
int f (int a, int b) { return x = a + b; }
class A { int x;
public: A (int n = 1) { x = n; }
int f () { return ::x = x; }
};
class B { int x;
public: B (int n = 2) { x = n; }
};
class C: public A, public B { int x;
public: int f (int a) { return ::x = x; }
void g ();
};
void C::g() { x = f ();
f (3);
x = f (4, 5);
x = 6;
}
int main () { C c;
c.f ();
c.f (7);
x = f (‘8’, 9);
return -1;
}
Ответ: C::x = A::f ();
C::f (3);
C::x = ::f (4, 5);
C::x = 6;
c.A::f ();
c.C::f (7);
::x =::f (‘8’, 9);
Отмечены исправляющие (обязательные) изменения.
Критерии: За каждое не отмеченное или неверное уточнение области видимости (из 7) -2. За каждое не найденное исправление (из 3) еще -3.
2. Есть ли ошибки в приведенном фрагменте программы на С++? Если есть, то объясните, в чем они заключаются. Ошибочные конструкции вычеркнуть из текста программы. Что будет выдано в стандартный поток вывода при работе программы?
class A {
public: virtual void f (int x) { h (x); cout << "A::f," << x << endl; }
void g () { h (0); cout << "A::g" << endl; }
virtual void h (int k) { cout << "A::h," << k << endl; }
};
class B: virtual public A {
public: void f (int y) { h (y); cout << "B::f," << y << endl; }
void g () { h (1); cout << "B::g" << endl; }
void h (int k) { cout << "B::h," << k << endl; }
};
int main( ){
A a; B b; A * p = & b;
p -> f (2);
p -> g ();
p -> h ();
p -> h (3);
}
Ответ: Ошибочным является вызов p -> h() (нет функции h() без параметров).
Будет выдано в поток: B::h,2 B::f,2 B::h,0 A::g B::h,3
Критерии: За каждую не найденную ошибку, лишнюю ошибку или неправильно вызванную функцию – 2.
3. Описать прототипы двух перегруженных функций f() из некоторой области видимости, для которых будут верны следующие обращения к ним:
f (0, 1); f (1, 0); f (0, "m"); f ("n", 0);
Ответ: void f (const char *, int);
void f (int, const char *);
Критерии: За каждую ошибку –5. Если приводятся прототипы более, чем двух функций –10. Пропуск слова const в обеих функциях одновременно считать за одну ошибку.
4. Для объектов из задания 1 определить, тела каких конструкторов и деструкторов (возможно пустые, если они не определены явно) и в каком порядке будут исполнены при работе следующего фрагмента программы:
int main () { C c; B b = c; A a = с; }
Ответ: A (), B (), C (), B (B &), A (A &), ~A (), ~B (), ~C (), ~B (), ~A ().
Критерии: За каждую ошибку –3.
5. Для класса комплексных чисел
template<class T> class complex { T r; T i; ... };
написать два варианта реализации операции "*", выполняющей умножение одного комплексного числа на другое методом класса и функцией-другом этого класса.
Ответ: template<class T> complex<T> complex<T>::operator*
(const complex<T>& x)
{ complex<T> w; w.r = r * x.r – i * x.i;
w.i = r * x.i + i * x.r; return w; }
template<class T> complex<T> operator*
(const complex<T>& x, const complex<T>& y)
{ complex<T> w; w.r = x.r * y.r – x.i * y.i;
w.i = x.r * y.i + x.i * y.r; return w; }
Критерий: За отсутствие каждого примера или ошибки в нем: -5.
6. Дать определения абстрактного типа данных и абстрактного класса в языке Си++. Есть ли различия в этих понятиях? Можно ли создавать объекты и описывать конструкторы этих типов?
Ответ: 1. Абстрактный тип данных есть тип данных с полностью скрытым (инкапсулированным) внутренним устройством. Работа с объектами абстрактных типов данных осуществляется с помощью специальных функций (доступных методов). Описывать конструкторы и создавать объекты абстрактных типов данных можно.
2. Абстрактный класс – это класс, содержащий чистые виртуальные функции. Объекты абстрактных классов создавать нельзя, но можно строить объекты классов, производных от абстрактных. В абстрактных классах могут быть конструкторы и деструкторы.
Критерий: За отсутствие каждого из определений: -5.
7. Что будет выдано в стандартный канал вывода при работе следующей программы?
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, 1);
cout << 12 << endl;
throw;
}
}
int main() { try { Y a; }
catch (...) { cout << 13 << endl;
return 0;
}
cout << 14 << endl;
return 0;
}
Ответ: 4 11 10 12 2 5 4 11 10 12 5 13 5
Критерии: За каждую неверную (лишнюю или пропущенную) печать -2.
8. Есть ли синтаксические ошибки в тексте приведенной программы? Можно ли исправить описание класса, не вводя дополнительных членов и не убирая имеющиеся, чтобы программа стала верной? Если да, то как?
class A { static int i;
static void f () { g (); cout << “f ()” << endl; }
void g () { if (i >= 0) i = -1, f ();
cout << “g ()” << endl; }
};
int A::i = 1;
int main () {
A::i = 1;
A a;
a.f();
a.i = 0;
}
Ответ: 1. Заменить слово “class” словом “struct”, либо вставить после открывающей фигурной скобки определения класса слово “public:”.
2. Cделать метод “g()” статическим.
Критерий: За пропуск ошибок доступа к закрытым членам класса: -5. За пропуск ошибки вызова нестатического метода: -5. За указание ошибки там, где ее нет: -5.
9. Описать последовательность отождествления типов параметров перегружаемых функций для случая функций с одним параметром. Приведите примеры для каждого из шагов последовательности.
Ответ: 1. Точное отождествление (с учетом вариантов синтаксической записи):
void f (double);
void f (int); void g () { ... f (1); ... } // f (int)
2. Безопасные расширения типов (char, short, enum, --> int (unsigned int); bool --> int; float --> double; double --> long double):
void f (float);
void f (long double); void g () {...f (1.0); ... } // f (long double )
3. Стандартные преобразования:
void f (char *); class A { ... };
void f (A); void g () { ... f (0); ... } // f (char *)
4. Пользовательские преобразования:
struct S { ... S (int); operator int ();... };
void e (int); void e (char *);
void f (S); void f (char *);
void g (S &a) { ... e (a); ... // e (int)
f (1); ... // f (S)
}
Критерий: За пропуск какого-либо одного из шагов или непонимание его сущности: -4. За пропуск других шагов или непонимание их сущности: -2 за каждый шаг. Отсутствие примеров при указании самого шага: -1 за каждый пропуск.
10. Написать функцию g() с тремя параметрами: непустой контейнер-вектор типа vector<int>, непустой контейнер-список типа list<int>, целое число – шаг по первому контейнеру. Функция должна, последовательно проходя по списку от начала к концу, перезаписывать на место очередного его элемента соответствующий очередному шагу элемент вектора (сам вектор при этом не изменяется), а затем распечатывать элементы списка в обратном порядке. Функция возвращает количество изменённых элементов списка.
Решение: typedef vector<int> V;
typedef list<int> L;
int g (const V & vect, L & lst, int step)
{ V:: const_iterator vp = vect.begin (); int t = 0;
L:: iterator lp = lst.begin ();
do { * 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. Если проверка на выход за границу вектора проводится в другом месте (например, в постусловии цикла) – не наказывать.