Показаны сообщения с ярлыком оператор. Показать все сообщения
Показаны сообщения с ярлыком оператор. Показать все сообщения

суббота, 2 апреля 2011 г.

53. Сколько операндов имеет операция индексирования []? Какой вид результата должна возвращать эта операция?

a. Ровно один операнд (параметр).
б. С точки зрения компилятора ничего она не должна и может возвращать что угодно. Или вообще не возвращать. Однако, я бы обиделся на std::vector, если бы не смог присваивать значения таким образом:
std::vector a(10);
a[3] = 42;

Поэтому, крайне желательно возвращать некоторое lvalue по ссылке, например:
double& operator[](int i){return _lvalue_;}

воскресенье, 14 ноября 2010 г.

34. Какие операции не рекомендуется перегружать как методы класса? Почему?

Даже и не знаю. Страуструп рекомендует перегружать как методы класса только те операторы, которым требуется изменить защищенные члены. Например:
class A{
  int x;
public:
  A& operator+=(int b){x+=b;} //Этому оператор изменяет защищенный член
}

//А этому не нужно менять, и он может воспользоваться оператором +=
A operator+(A& a, int b){A res = a; return res+=b;}

33. Что означает выражение *this? В каких случаях оно используется?

Разыменованный указатель на себя. Часто используется, если функции-члену класса нужно вернуть ссылку на текущий объект:
class A{
  int x;
public:
  A& operator=(const A& a){x = a.x; return *this;} 
}

32. Как различаются перегруженная префиксная и постфиксная операции инкремента и декремента?

Выражение ++a компилятор превращает в вызов operator++(a), а для a++ в вызов operator++(a, int). Параметр int добавлен только для различия сигнатур функций и его значение не используется. Аналогично для декремента.

31. Какой результат должны возвращать операции с присваиванием?

Вообще говоря, ничего они не должны. Однако, для всех классов, по умолчанию, этот оператор означает копирование объекта и возвращение ссылки. Поэтому, при переопределении оператора, отступать от этого правила нежелательно. Но мы не обязаны использовать этот оператор только для копирования объектов.

class A{
public:
  int x;
  A& operator=(const A& a){x = a.x; return *this;} //переопределили стандартное поведение
  void operator=(int xx){x=xx;} //определили поведение при присваивании целого. Но здесь тоже можно вернуть *this.
};

int main(){
  A a;
  a=1;
  A a2;
  std::cout << (a2=a).x;
}

пятница, 29 октября 2010 г.

30. Перечислите особенности перегрузки операций как методов класса. Чем отличается перегрузка внешним образом от перегрузки как метода класса?

  • Первый параметр оператора опускается, им становится экземпляр класса (this).
  • Его можно сделать константным методом.
  • У него имеется доступ к не-public членам.
  • Оператор можно сделать виртуальным.
Этим и отличается.

среда, 27 октября 2010 г.

29. Можно ли определить новую операцию?

Нельзя. Технически это было бы несложно, но создало бы больше проблем, чем решило. Допустим, мы решили добавить операцию **, означающую в некоторых языках возведение в степень. Посмотрим, какие возникают трудности.
  • Неоднозначность. Как интерпретировать a**b? (a)**(b) или a*(*b). Заметьте, оба варианта синтаксически корректны, но имеют разный смысл. Придется создавать правила для разрешения этой ситуации.
  • Ассоциативность. Чему эквивалентно a**b**c? (a**b)**c или a**(b**c)?
  • Приоритет. Чему эквивалентно a+b**c? (a+b)**c или a+(b**c)?
Напоминаю, с точки зрения разработчика языка, проблемы не являются неразрешимыми. В некоторых языках есть такая возможность.

вторник, 26 октября 2010 г.

28. Можно ли при перегрузке изменить приоритет операции?

К счастью, нет :) Это создало бы слишком много проблем.

понедельник, 25 октября 2010 г.

27. Можно ли перегружать операции для встроенных типов данных?

Нет. Вообще, хотя бы одно из значений оператора должно являться пользовательским типом.

воскресенье, 24 октября 2010 г.

26. Какие операции нельзя перегружать? Как вы думаете, почему?

По-моему, чаще используется слово "оператор", я так и буду их называть.
Перегружать можно следующие операторы:
+ - * / % ^ & | ~ ! = < >
+= -= *= /= %= ^= &= |=
<< >> >>= <<= == != <= >=
&& || ++ -- ->* , -> [] ()
new new[] delete delete[]


А нельзя (подсмотрел у Страуструпа):
  • :: (разрешение области видимости)
  • (выбор члена)
  • .* (выбор члена через указатель на член)
  • ?: тернарный оператор
  • sizeof, typeid
У первых трех в правой части имя, а не значение. У тернарного оператора аж 3 параметра, к тому же его возвращаемое значение является l-value. Переопределять sizeof, typeid, думаю, просто нет смысла.
Также нельзя определить новые лексемы.