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


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0503 ]   [ 16 queries used ]   [ Generated: 27.04.24, 13:18 GMT ]