Автор
|
Тема: Наследование перегруженого operator =
|
server_mouse |
опубликован 29-12-2001 17:24 MSK
Есть класс с перегруженым оператором =. Делаю наследника, и тот почему-то не наследует эту перегрузку, пытаясь сделать binary copy. Попытка сделать его virtual не помогла. Неужто его нужно обязательно явно переопределять?
|
zAg
|
опубликован 29-12-2001 19:36 MSK
Я сначала подумал что это особенность VC (в CB таких проблем не было), но щас попробовал - такая конструкция работает и там и там:class base{ public: base& __fastcall operator=(base &mc); }; base& __fastcall base::operator=(base &mc) { return *this; } class derived:public base{ }; derived a,b; a=b; ?? |
zAg
|
опубликован 29-12-2001 19:37 MSK
Вызывается именно base::operator= |
server_mouse
|
опубликован 03-01-2001 10:12 MSK
Вот такой код не работает! //------------- str.h ---------------- class CStr { public: char* str; CStr& __fastcall operator = (const char* _str); CStr& __fastcall operator = (CStr& _str); operator LPCTSTR () const; virtual ~CStr(); };class CStr2:public CStr { public: CStr2(); virtual ~CStr2(); }; //---------------------------------- //----------- str.cpp -------------- #include "str.h" CStr& __fastcall CStr::operator = (CStr& _str) { return *this; } CStr& __fastcall CStr::operator = (const char* _str) //Çàãðóçêà èç ñòðîêè { //Тут всякая шняга return *this; } CStr::operator LPCTSTR () const { return str; } //-------------------------------- //Конструкторы/деструкторы не описывал. //Они вам нужны??? main() { CStr str1; str1="test1"; CStr2 str2; str2="test"; } Именно на последнюю строку и ругается компилятор: error C2679: binary '=' : no operator defined which takes a right-hand operand of type 'char [5]' (or there is no acceptable conversion) Как я понял он пытается сделать побайтное копирование... Вправте ручки. |
Valery
|
опубликован 03-01-2001 11:09 MSK
2server_mouse: ой, тяжко, конечно после нового года вспоминать всякое, но тем не менее: оператор= как и конструктор предоставляется компилятором по умолчанию и не наследуется, вот не помню, можно ли его делать виртуальным. А поэтому тебе придется описывать в производном классе оператор присваивания с такой же сигнатурой, если ты хочешь, чтобы срабатывал такой же синтаксис. и ужо внутри перевызывать оператор присваивания для базового класса. |
Valery
|
опубликован 03-01-2001 11:12 MSK
проверил, делать виртуальным его можно, но вот теперь не могу понять - нафига :) тяжко... |
Valery
|
опубликован 03-01-2001 11:22 MSK
что значит, все-таки, чашечка хорошего кофе! и нужен и вполне применим, даже в твоем случае: CStr *s = new CStr2; *s = "aaaaaaaaa";будет работать даже без объявления в производном классе оператора присваивания с этой сигнатурой.
|
sergeyMJ
|
опубликован 03-01-2001 12:41 MSK
А вот такой код работать не будет,CString s1; s1 = "Ex2" + "Ex2"; А такой будет: CString s2= "Hello"; s1 = "Ex2" + s2+ "Ex2";
|
Valery
|
опубликован 03-01-2001 13:12 MSK
при чем здесь это? здесь ты присваиваешь результать оператора +, а он как известно возвращает CString, то бишь объект того же класса. Уж для него-то компилятор способен состряпать конструктор копии, правда в этом случае это не надо, он описан в классе CString. Первый твой пример не работает потому что нет (да и не может быть) внешнего оператора +, который бы складывал два указателя на char в стороку типа CString. А во втором случае все достаточно штатно - к объекту CString прибавляется LPCTSTR, а потом еще раз, все за счет вот этих двух объявлений:friend CString operator +( const CString& string, LPCTSTR lpsz ); throw( CMemoryException ); friend CString operator +( LPCTSTR lpsz, const CString& string ); throw( CMemoryException ); Вот собственно и все. А в чем траблы?
|
sergeyMJ
|
опубликован 03-01-2001 13:41 MSK
А почему мы не можем перегрузить friend CString operator +( LPCTSTR lpsz, LPCTSTR lpsz ); throw( CMemoryException ); |
zAg
|
опубликован 03-01-2001 14:02 MSK
2server_mouse: И в самом самом деле чето не пашет...Если только так: (CStr&)str2="test"; и если нужно определить CStr2::operator CStr() но это конечно не то... кстати оказывается в описанной мной схеме работает только derived::operator=(derived),а derived::operator=(base) работать уже не будет >:[ Хотя по идее именно он работать и должен.ps. И вообще нафиг тебе наследник для строкового класса? Неужели одним классом нельзя обойтись?
|
Valery
|
опубликован 03-01-2001 14:03 MSK
стандарт языка требует, чтобы при перегрузке бинарных операторов в виде внешней функции хотя бы один из их параметров был _обязательно_ пользовательским типом. Требование введено для того, чтобы язык был _расширяемым_, а не _меняющимся_. |
zAg
|
опубликован 03-01-2001 14:27 MSK
И вообще перегрузка операторов(особенно =) ИМХО снижает наглядность. Например будут *str1,*str2 ,забудешь что это указатели и напишешь str1=str2 думая что скопируются строки - получится неприятность :) Я в подобных случаях вместо operator= определяю метод Assign(школа VCL :)) Тогда все наследуется как надо: str2.Assign("test") или в случае указателя : str2->Assign("test") - по-моему неплохо смотрится :) да и ошибок никогда не будет.
|
Valery
|
опубликован 03-01-2001 14:53 MSK
Хорошо подобранный набор операций имхо наоборот повысит наглядность, хотя, как и в любом деле здесь необходимо чувство меры. А насчет примера с указателями на символ вместо сторок - давно уж говорится не думайте, что это строки. Я если их использую, то только где-то в потрохах классов или когда необходимо интерфейс а-ля Сишка предоставить. А так предпочитаю эстээлевские стороки (в этом месте могла бы быть ваша реклама :) |
zAg
|
опубликован 03-01-2001 15:44 MSK
Под наглядностью я имел в виду вот что: наткнувшись где то в недрах кода на запись a=b ничего нельзя сказать что здесь реально делается :то ли это binary copy то ли перегруженный оператор= или может a и b указатели на объекты? А вот в случае a.Assign(b) или a->Assign(b) - сразу понятно ,что: 1. объект a копирует объект b явно определенным способом 2. cами ли это объекты или указатели на нихps. для строкового класса возможно имеет смысл определить operator=, но в общем случае для копирования лучше завести спец. метод (ИМХО) |
Valery
|
опубликован 03-01-2001 16:04 MSK
присваивание нагляднее в том плане, что это стандартная ++-ность, не суть важно как при этом происходит копирование - глубокое с использованием конструкторов копирования всех вложенных сущностей или простое бинарное. Меня это не должно волновать - класс должен быть спроектирован так чтобы делать это без сюрпризов. По поводу указателей - отдельная тема, очень емкая. Функция Assign() в твоем случае - лишь замена синтаксиса, привычная тебе, тот кто столкнется с ней впервые, также полезет в исходники функции, чтобы понять чего она делает. Все вышесказанное также имхо. Вообще мы с тобой начинаем спорить о вкусах, а это занятие бесперспективное. |