Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[13.58.247.31] |
|
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Есть класс с перегруженым оператором =. Делаю наследника, и тот почему-то не наследует эту перегрузку, пытаясь сделать binary copy. Попытка сделать его virtual не помогла. Неужто его нужно обязательно явно переопределять?
|
Сообщ.
#2
,
|
|
|
Я сначала подумал что это особенность 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; ?? |
Сообщ.
#3
,
|
|
|
Вызывается именно base::operator=
|
Сообщ.
#4
,
|
|
|
Вот такой код не работает!
//------------- 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) Как я понял он пытается сделать побайтное копирование... Вправте ручки. |
Сообщ.
#5
,
|
|
|
2server_mouse:
ой, тяжко, конечно после нового года вспоминать всякое, но тем не менее: оператор= как и конструктор предоставляется компилятором по умолчанию и не наследуется, вот не помню, можно ли его делать виртуальным. А поэтому тебе придется описывать в производном классе оператор присваивания с такой же сигнатурой, если ты хочешь, чтобы срабатывал такой же синтаксис. и ужо внутри перевызывать оператор присваивания для базового класса. |
Сообщ.
#6
,
|
|
|
проверил, делать виртуальным его можно, но вот теперь не могу понять - нафига тяжко...
|
Сообщ.
#7
,
|
|
|
что значит, все-таки, чашечка хорошего кофе!
и нужен и вполне применим, даже в твоем случае: CStr *s = new CStr2; *s = "aaaaaaaaa"; будет работать даже без объявления в производном классе оператора присваивания с этой сигнатурой. |
Сообщ.
#8
,
|
|
|
А вот такой код работать не будет,
CString s1; s1 = "Ex2" + "Ex2"; А такой будет: CString s2= "Hello"; s1 = "Ex2" + s2+ "Ex2"; |
Сообщ.
#9
,
|
|
|
при чем здесь это?
здесь ты присваиваешь результать оператора +, а он как известно возвращает 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 ); Вот собственно и все. А в чем траблы? |
Сообщ.
#10
,
|
|
|
А почему мы не можем перегрузить
friend CString operator +( LPCTSTR lpsz, LPCTSTR lpsz ); throw( CMemoryException ); |
Сообщ.
#11
,
|
|
|
2server_mouse:
И в самом самом деле чето не пашет...Если только так: (CStr&)str2="test"; и если нужно определить CStr2::operator CStr() но это конечно не то... кстати оказывается в описанной мной схеме работает только derived::operator=(derived),а derived::operator=(base) работать уже не будет >:[ Хотя по идее именно он работать и должен. ps. И вообще нафиг тебе наследник для строкового класса? Неужели одним классом нельзя обойтись? |
Сообщ.
#12
,
|
|
|
стандарт языка требует, чтобы при перегрузке бинарных операторов в виде внешней функции хотя бы один из их параметров был _обязательно_ пользовательским типом.
Требование введено для того, чтобы язык был _расширяемым_, а не _меняющимся_. |
Сообщ.
#13
,
|
|
|
И вообще перегрузка операторов(особенно =) ИМХО снижает наглядность. Например будут *str1,*str2 ,забудешь что это указатели и напишешь str1=str2 думая что скопируются строки - получится неприятность
Я в подобных случаях вместо operator= определяю метод Assign(школа VCL ) Тогда все наследуется как надо: str2.Assign("test") или в случае указателя : str2->Assign("test") - по-моему неплохо смотрится да и ошибок никогда не будет. |
Сообщ.
#14
,
|
|
|
Хорошо подобранный набор операций имхо наоборот повысит наглядность, хотя, как и в любом деле здесь необходимо чувство меры. А насчет примера с указателями на символ вместо сторок - давно уж говорится не думайте, что это строки. Я если их использую, то только где-то в потрохах классов или когда необходимо интерфейс а-ля Сишка предоставить. А так предпочитаю эстээлевские стороки (в этом месте могла бы быть ваша реклама
|
Сообщ.
#15
,
|
|
|
Под наглядностью я имел в виду вот что: наткнувшись где то в недрах кода на запись a=b ничего нельзя сказать что здесь реально делается :то ли это binary copy то ли перегруженный оператор= или может a и b указатели на объекты?
А вот в случае a.Assign(b) или a->Assign(b) - сразу понятно ,что: 1. объект a копирует объект b явно определенным способом 2. cами ли это объекты или указатели на них ps. для строкового класса возможно имеет смысл определить operator=, но в общем случае для копирования лучше завести спец. метод (ИМХО) |