Re[21]: Перегрузка операторов
От: Red Line  
Дата: 25.05.04 16:06
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Red Line, Вы писали:


К>
RL>>// Операции с указателем
RL>>>>T& operator*() { assert(m_pI != NULL); return *m_pI; }
К>

RL>>Я ни как не вразумею, — как нужно читать синтаксис этого оператора.

К>Проще некуда:

К>
К>struct Data
К>{
К>  int x;
К>  void foo();
К>};

К>// некоторые функции...
К>void accept_data(Data d); // входной параметр
К>void fill_data(Data& d); // выходной параметр


К>struct SmartPtr
К>{
К>  Data* p;

К>  Data& operator* () { return *p; }
К>};

К>main()
К>{
К>  Data* p1;
К>  SmartPtr p2;
К>  . . . . .

К>  // обычный указатель      // явный доступ к члену умного     // то же самое,
К>                            // -- обычному указателю           // но завёрнутое в оператор разыменования
К>  fill_data(*p1);           fill_data(*(p2.p));                fill_data(*p2);
К>  accept_data(*p1);         accept_data(*(p2.p));              accept_data(*p2);
К>}
К>

К>Видишь, что внешне работа с обычным указателем (левый столбец) выглядит так же, как с умным (правый).
К>Перекрытый оператор служит именно этой цели: одинаковости внешнего вида.

RL>>Мне понятна запись:

RL>>
RL>>С operator + (const C lPar, const C rPar);
RL>>


RL>>Читаю (в соответствии с тем как Вы меня учили)

RL>>Внешний оператор;
RL>>двухместный инфиксный оператор (операнд слева — lPar, операнд справа — rPar);

RL>>Возможны две формы вызова

RL>>явная:
К>
RL>>C x,y,z;

RL>>z = +(x,y);
К>

RL>>и операторная:
К>
RL>>С x,y,z;

RL>>z = x+y;
К>

RL>>Верно?

К>Неверно!!!

К>Операторная запись:
К>
 z = x+y;

К>Функциональная запись (если оператор внешний):
К>
 z = operator+ (x,y);

К>Функциональная запись (если оператор — функция-член):
К>
 z = x.operator+ (y);


RL>>Теперь оператор-член класса:

RL>>
RL>> class С
RL>>{
RL>>  C add(val1, val2);
RL>>  C operator + (C rPar) const {return add(*this, rPar);}
RL>>};
RL>>

RL>>Оператор-член класса; (подразумевается, что если левый аргумент не указан то это всегда *this)

К>Он не "если не указан", а всегда не указан. У любого метода объекта есть неявный параметр — указатель на сам объект.


RL>>двухместный (бинарный) и вроде бы инфиксный;


RL>>Явная форма вызова:

К>
RL>>С obj;
RL>>C anyPar;
RL>>C res;
RL>>res = obj.operator + (anyPar);
К>
//равносильно obj+anyPar? Т.е текущий объект складывается с параметром, и что будет блин не догоняю ((


RL>>Операторная форма:

К>
RL>>С obj;
RL>>C anyPar;
RL>>C res;

RL>>res = +anyPar;
К>

К>// правый операднд (параметр) указан явно, а левый есть объект. Какой??? anyPar-объект, а тот что в операторе где????

К>Ещё раз. Операторная форма записи НИЧЕМ не отличается от операций над арифметическими типами.

К>Ключевое слово "operator" — это НЕ ОПЕРАТОРНАЯ ФОРМА ЗАПИСИ. А функциональная.

RL>>Мне бы хотелось в такой же форме разобрать и эти операторы:

RL>>
RL>> class cPtr
RL>>{
RL>>   private:
RL>>   T* p;//указатель на искомый интерфейс
RL>>   public:
RL>>   operator T*() {  return m_pI; }
RL>>   T& operator*() { return *m_pI; }
RL>>   T** operator&() { return &m_pI; }
RL>>   T* operator->() { return m_pI; }
RL>>};

RL>>

RL>>Прошу извинить если надоедаю

К>Ну и что здесь непонятного? Попробуй поработать за компилятора.

К>
К>void foo(T* pointer);
К>void bar(T value);
К>void xyz(T& reference);
К>void get(T** address_of_pointer);

К>main()
К>{
К>  cPtr ptr;

К>  get(&ptr);              get(&(ptr.m_pI));
К>  foo(ptr);               foo(ptr.m_pI);
К>  bar(*ptr);              bar(*(ptr.m_pI));
К>  xyz(*ptr);              xyz(*(ptr.m_pI));
  ptr->>call();            ptr.m_pI->call();
К>}
К>



// обычный указатель      // явный доступ к члену умного     // то же самое,
К>                            // -- обычному указателю           // но завёрнутое в оператор разыменования
К>  fill_data(*p1);           fill_data(*(p2.p));                fill_data(*p2);
К>  accept_data(*p1);         accept_data(*(p2.p));              accept_data(*p2);


Кажется я понял !!!



 fill_data(*p2);
 accept_data(*p2);


*p2 — это и есть вызов операторной функции, т.е не звёздочка сама по себе, а именно "*p2" и есть вызов
аналогичный p2.operator*() для экземпляра p2... Этот вызов приведёт к тому, что отработает код:

 return *p;


и функция accept_data получит аргумент верного тип (типа Data).

Ну так или нет?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.