Давным-давно, когда я искал работу, мне прислали одну интересную задачку, которую я до сих пор гуглю на просторах интернета. Причем гуглю безответно - народ ломает голову, но ничего толкового придумать не может.
Я не самый большой специалист по С++, поэтому тешу себя мыслью, что если я ошибаюсь - меня поправят, а если нет - пусть статья выходит в топы гугла и висит там, дабы ее прекратили давать на собеседованиях. Потому что задача идиотская.
Звучит она так:
Перегрузка оператора присваивания
Пусть есть класс
class Boo : public SuperBoo
{
Foo* fFoo1;
Foo* fFoo2;
}
Где Foo - мономорфный класс, а класс Boo владеет указателями fFoo1, fFoo2.
Задача: перегрузить оператор присваивания для класса Boo.
Начнем с первого - с мономорфного класса. Все знают, что ООП состоит из полиморфизма, инкапсуляции и наследования. Определение полиморфизма можно
прочитать в википедии, а пользуясь нехитрой логикой можно понять, что мономорфный - антоним понятия «полиморфный». Таким образом, в нашем случае, мономорфный класс - это класс, указатель на который всегда представляет его самого, а не его наследника.
То есть мы можем гарантировать то, что за Foo* скрывается класс Foo, а не какой-нибудь class MegaFoo : public Foo.
Второй вывод, который мы можем сделать из текста задачи - что класс Boo владеет указателями, а значит удаляет их в деструкторе. Таким образом, нам необходимо помнить о политике владения при написании оператора присваивания и четко удалять и создавать новые объекты.
Третий вывод позволяет нам сделать наличие суперкласса у Foo. Вполне возможно, что у SuperFoo есть оператор присвания, а значит нам необходимо его вызвать. Если же его нет - не беда, всегда есть оператор присваивания по умолчанию, просто копирующий блок памяти.
Таким образом, по нашему трезвому измышлению, необходимо сделать следующее для успешного написания оператора присванивания:
- Вспомнить синтаксис оператора присваивания
- Удалить fFoo1 и fFoo2
- Вызвать родительский оператор присваивания
- Сделать копии fFoo1 и fFoo2 у правой части оператора
- Вернуть ссылку на себя
В коде это будет выглядеть следующим образом:
Boo& operator=(const Boo& other)
{
delete this->fFoo1;
this->fFoo1 = nullptr;
delete this->fFoo2;
this->fFoo2 = nullptr;
SuperBoo::operator=(other);
if(other.fFoo1)
this->fFoo1 = new Foo(*other.fFoo1);
if(other.fFoo2)
this->fFoo2 = new Foo(*other.fFoo2);
return *this;
}
Это я и выслал в ответ на «тестовое задание», на что мне было сказано, что с заданием я не справился.
До сих пор гадаю, где же ошибка? На ум, конечно, приходит консистентность данных, защита от сбоев при выделении памяти и прочие кошерные вещи, но тут уже мой разум пасует - не настолько хорошо я знаю С++.
Комментировать запись на virtualmind.ru