пятница, 19 ноября 2010 г.

Вопрос претенденту на вакансию "Программист C++"

На нескольких сайтах, предлагающих вакансию программиста C++, встречаются одни и те же вопросы, например, на сайте вакансий yandex. Один из них такой:
Перечислите все проблемы, которые вы видите в данном коде:


1 class Foo
2 {
3 public:
4 Foo(int j) { i=new int[j]; }
5 ~Foo() { delete i; }
6 private:
7 int* i;
8 };
9
10 class Bar: Foo
11 {
12 public:
13 Bar(int j) { i=new char[j]; }
14 ~Bar() { delete i; }
15 private:
16 char* i;
17 };
18
19
20 void main()
21 {
22 Foo* f=new Foo(100);
23 Foo* b=new Bar(200);
24 *f=*b;
25 delete f;
26 delete b;
27 }



В результате медитации, получил следующий, несовершенный код, но все же отражающий моё понимание проблем:

1 class Bar;//Добавил, чтоб в классе Foo использовать имя класса Bar
2
3 class Foo
4 {
5 public:
6 Foo(int j)
7 {
8 i=new int[j];
9 }
10 Foo() {} //Добавил, т.к. нужен конструктор по умолчанию, если бы Foo(int),
» небыло, то он бы был сгенерирован компилятором

11 ~Foo()
12 {
13 delete[] i; //Изменил, добавив [], а то удалять будет не весь массив, а
» только первый элемент массива с индексом 0, т.е. получим утечку памяти

14 }
15
16 Foo operator=(const Bar& r_)//Добавил оператор присваивания, и по идее надо
» делать глубокое копирование по членам, но для этого обеспечить доступ к полю
» Bar::i, вариантов может быть несколько

17 {
18 //На самом деле дальше код должен быть более сложный
19 delete[] i; //в общем, то надо ещё поработать с динамической памятью,
» убрать, то, что там было создано конструктором Foo(int), а то будет утечка
» памяти

20 return Foo();//сделаем так для простоты
21 }
22
23
24
25 private://Возможно надо заменить private на protected, чтоб дочерний класс мог
» обращаться к полю Foo::i

26 int* i;
27 };
28
29 class Bar: public Foo //добавил public
30 {
31 public:
32 Bar(int j)
33 {
34 i=new char[j];
35 }
36 ~Bar()
37 {
38 delete[] i; //Изменил, добавив []
39 }
40
41 private:
42 char* i;
43 };
44
45
46 int main()
47 {
48 Foo* f=new Foo(100);
49 Foo* b= new Bar(200); //Нужно в классе определить присваивание и чтоб было
» открытое наследование

50 *f=*b; //Нужно в классе определить присваивание
51 delete f;
52 delete b;
53 }



Ах, да, похоже, что надо ещё создать конструктор копирования Foo(const Foo&), надо повозится с глубоким копированием, сделать проверки в операторе присваивания, чета стало лень копать дальше.