| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Для новичков > Что делать с возвращаемым значением в потомке |
| Автор: EvilsInterrupt 27.7.2009, 12:52 | ||
| Есть Base и Child классы, в них перегружены оператор operator= т.е код:
Вопрос в коментарии ;) |
| Автор: mes 27.7.2009, 13:25 |
| а Вас не смущает, что сигнатура у Ваших операторов разная ? И вобще какого поведения Вы хотите добиться, делая оператор= виртуальным ? |
| Автор: GoldFinch 27.7.2009, 13:42 |
| EvilsInterrupt, значение возвращаемое бинарными операторами нужно чтобы была возможность его использовать например foo(a=b), c=(a=b) если ты не собираешься чтото с ним делать - игнорируй его. |
| Автор: Леопольд 28.7.2009, 07:11 | ||||
Если я правильно понял вопрос, то ответ такой. А вообще, желательно задавать более исчерпывающие вопросы. Так больше шансов получить нужный ответ.
|
| Автор: mes 28.7.2009, 09:24 | ||||||
хотел бы посмотреть как автор справится с правильной реализаций поведения этой семантики тут можно писать
тогда в выражении
в первом присваивании вызовется нужный оператор =(const Child&), а не =(const Base&), как в примере выше. и не помешало бы добавить в строки вывода комментария отличия, чтоб различать какой оператор вызвался например тип параметра :
|
| Автор: EvilsInterrupt 28.7.2009, 10:24 | ||
| Вопрос возник в связи следующей ситуаций Есть базовый - Base1 и есть потомки Child1, Child2, ... ,ChildN Начал реализовывать копирующее присваивание и копирующую инициализацию. Чтобы имея уже созданного и рабочего потомка Child1 можно было запросто присвоить в только что созданного потомка Child2 . Пример:
Вывод : в базовом нужно указать что в потомка будут оператор присваивания и копирующий конструктор, при этом они не будут запрещены(т.е. не закинуты в приват часть), тогда программер делающий реализацию очередного потомка будет точно знать , что ему нужно реализовать! Т.е. Base для него будет - чертежом. Однако, часть реализации уже можно реализовать копирующем конструкторе и в методе присваивания базового класса, а уж частности, т.е. специфичные вещи, в потомке. Возникает вопрос если в базовом методе присваивания возвращает тип ссылку на себя: Base & operator=(const Base & rBase); то при вызове этого метода в потомке что делать с этим возвращаемым значением ? + Вы правильно заметили про сигнатуру, т.е. прототип метода присваивания в потомке, особо не понимаю каким он должен быть(о прототипе) ? Точь в точь как и в базовом или нет? ЗЫ: И прошу прощения за мои сумбурные темы ;) К сожалению не адвансед тех. врайтер, но стараюсь хоть чуточку описать по понятней, но как обычно "хотел как лучше, а вышло как всегда" ;) |
| Автор: bsa 28.7.2009, 10:30 | ||
| EvilsInterrupt, обычно, классы, которые имеют виртуальные методы, не присваивают друг другу. Так как присваивание потомка предку или потомку с параллельной ветки по любому приведет к "срезке" (т.е. скопируются данные только общего базового класса). Поэтому с подобными объектами работа ведется через указатели или ссылки. Как вариант, можно сделать виртуальный метод clone, который будет возращать указатель на клон текущего объекта. А чтобы организовать семантику присваивания, то необходимо все это завернуть в "умный указатель". Поведение которого такое же как у класса, но сам он содержит только указатель на базовый класс (что-то вроде паттерна pimpl). Пример базового класса:
|
| Автор: EvilsInterrupt 28.7.2009, 10:44 | ||
Почему ? Мне бы приятно было видеть с эстетической точки зрения код вида: mem_strm = file_strm; чем: mem_strm = file_strm.clone(); да и наглядней ;) |
| Автор: Леопольд 28.7.2009, 10:45 | ||||||
Мне кажется что правильнее всё же будет вызывать через один интерфейс. А если возвращать Child то он всё равно будет сведён к ссылке на базовый класс (интерфейс) Видимо требуется вот такое поведение, только я пока не понял зачем. Если эти классы инкапсулируют различные данные, то каким образом осуществлять присвоение по ссылке на базовый? А если данные одинаковые, то нафига нужны разные классы?
|
| Автор: bsa 28.7.2009, 11:05 | ||||||
Потому что ты напрямую не будешь использовать указанные классы:
|
| Автор: mes 28.7.2009, 11:08 | ||
тогда зачем второй оператор = добавили в наследника ?! В Вашем случае получается что, в в первом вызове оператора (для a1=a2) при a1=a2=a3 вызовется =(const ChildA&) при a1=а2=b1 вызовется =(const Base&) имхо, не очень логично.. как в принципе и само решние делать данный оператор виртуальным. |
| Автор: Леопольд 28.7.2009, 11:11 | ||||||||
Для присвоения указателей они дожны быть одного типа. Может имелось ввиду следующее? // Много кода *pChild2 = *pChild1; // [1] копирующее присванивание Можно написать конструктор принимающий ссылку на базовый класс, который будет инициализирвать общую, базовую часть
Добавлено @ 11:15
согласен, больше не кажется |
| Автор: mes 28.7.2009, 11:15 | ||
добавлю, что вместо 0, можно использовать объект dummy класса, тогда 1. не нужна будет проверка в методах враппера ("умного указателя") на нуль . 2. ответы на get методы будут реализованы в наследнике (этом dummy классе), а не во враппере. Добавлено через 1 минуту и 32 секунды
можно.. но в общем случае этот повлечет потерю части информации, что не очень соответсвует семантики копирования |
| Автор: Леопольд 28.7.2009, 11:21 | ||||
для этого, в этом конструкторе, должны ещё как-то инициализироваться остальные данные (базовая часть инициализируется из объекта другого типа) Добавлено через 4 минуты и 10 секунд
что в свою очередь приводит к потере интуитивности. |
| Автор: mes 28.7.2009, 11:27 | ||||||||
тогда проблема будет тут :
имхо, сказанному в цитате, соответствует такая запись
но никак не копирование. Добавлено через 5 минут и 7 секунд |