2010-07-06 3 views
4

С точки зрения дизайна языка, Какой тип практики поддерживает перегрузку оператора?Перегрузка оператора

Каковы преимущества & минусов (если есть)?

+1

Возможный дубликат http://stackoverflow.com/questions/77718 – krock

ответ

16

EDIT: было отмечено, что std::complex гораздо лучший пример, чем std::string для «хорошего использования» перегрузкой операторов, поэтому я в том числе пример того, что, как хорошо:

std::complex<double> c; 
c = 10.0; 
c += 2.0; 
c = std::complex<double>(10.0, 1.0); 
c = c + 10.0; 

Помимо синтаксис конструктора, он выглядит и действует так же, как и любой другой встроенный тип.


Основной профессионал в том, что вы можете создавать новые типы, которые действуют как встроенные типы. Хорошим примером этого является std::string (см. Выше для лучшего примера) в C++. Это реализовано в библиотеке и не является базовым. Однако вы можете писать такие вещи, как:

std::string s = "hello" 
s += " world"; 
if(s == "hello world") { 
    //.... 
} 

Недостатком является то, что его легко злоупотреблять. Плохой выбор при перегрузке оператора может привести к случайно неэффективному или нечеткому коду. Представьте, если std::list имел operator[].Вы можете захотеть, чтобы написать:

for(int i = 0; i < l.size(); ++i) { 
    l[i] += 10; 
} 

это O (N^2) алгоритм! Уч. К счастью, std::listне имеют operator[], так как предполагается, что это эффективная операция.

+0

+1 для примера с хорошим списком. – martiert

+1

«Хороший пример» с очевидным оговоркой, что определение оператора + для строк немного нехорошо ..., 9 – jalf

+2

Почему это хороший пример? 'operator +' является коммутативным для всех встроенных типов, но не для 'std :: basic_string', поэтому можно даже сказать, что это злоупотребление перегрузкой оператора. «std :: complex» может служить лучшим примером. – Philipp

6

Плюсы: вы можете получить код, который проще читать. Мало кто будет спорить, что:

BigDecimal a = x.add(y).divide(z).plus(m.times(n)); 

как легко читается как

BigDecimal a = ((x + y)/z) + (m * n); // Brackets added for clarity 

Минусы: это труднее сказать, что называют. Кажется, я помню, что в C++, заявление формы

a = b[i]; 

может в конечном итоге выполнение 7 пользовательских операций, хотя я не могу вспомнить, что все они. Я могу быть немного «выключен» на примере, но принцип прав - перегрузка оператора и пользовательские преобразования могут «спрятать» код.

+0

Только один, насколько я могу судить. Он должен вызывать оператор присваивания. Конечно, это может вызвать столько других операций, сколько им нравится. ('A a = b', с другой стороны, вызвал бы конструктор копирования;)) – jalf

+0

Он также может применять преобразование. – visitor

+0

@visitor: Я думаю, что пропустил индексирование :) Будет ли редактировать ... –

13

Первоначальный драйвер обычно является математикой. Программисты хотят добавить векторы и кватернионы, написав a + b и умножить матрицы на векторы с M * v.

Он имеет гораздо более широкий охват, чем это. Например, интеллектуальные указатели выглядят синтаксически, как обычные указатели, потоки могут немного походить на трубы Unix, и различные пользовательские структуры данных могут использоваться так, как если бы они были массивами (со строками как индексы, даже!).

Общий принцип перегрузки заключается в том, чтобы позволить разработчикам библиотек улучшить язык в бесшовной форме. Это и сила, и проклятие. Это дает очень мощный способ сделать язык более богатым, чем он есть, но он также очень уязвим для злоупотреблений (более того, чем многие другие функции C++).

+0

Я согласен, когда вы говорите, что это и сила, и проклятие, но каждая сила в программировании также является проклятием, разве это не так? Все может быть использовано неправильно. Перегрузка оператора позволяет программистам создавать еще худшие интерфейсы, позволяя устанавливать переменные (императивное программирование), позволяя программистам создавать неправильные имена переменных, отражение позволяет программистам испортить свой объектконтекст, отладчики делают программников менее осторожными, а среды IDE делают ленивых программистов. Я бы подумал, что все эти вещи оказывают положительное влияние на программирование, но все они имеют возможность использовать их неправильно. –

+0

@B T: Это все утверждения материнства. Если абсолютно что-то можно охарактеризовать как силу и проклятие, то фраза становится бессмысленной. Понятно, что мое намерение заключалось в том, чтобы выразить мнение о том, что перегрузка оператора особенно подвержена злоупотреблениям, в той мере, в которой возможность устанавливать переменные или создавать массивы или выполнять итерацию в цикле или функции вызова не являются. –

1

Вы можете сделать несколько интересных трюков с синтаксисом (то есть потоками на C++), и вы можете сделать код очень кратким. Тем не менее, вы можете заставить код очень сложно отлаживать и понимать. Вы должны постоянно быть настороже о влиянии различных операторов различных объектов.

+1

Операторы C++ '<<' and '>> являются каноническим * неудачным примером перегрузки оператора. Их использование для потоков не имеет ничего общего с их первоначальным значением. – dan04

+0

@ dan04: С другой стороны, '<<' and '>>' довольно жалкие встроенные операторы сами по себе. Они не имеют никакого значения для людей, незнакомых с C и его похожими, они определены только для подмножества встроенных типов, и даже для типов, которые они работают над результатами, не всегда четко определены. Они могут проиллюстрировать плохую перегрузку, но они также иллюстрируют, почему рекомендации иногда могут быть согнуты для хорошего использования. –

0

Вы можете считать перегрузкой оператора как своего рода перегрузку метода/функции. Это часть полиморфизма в объектно-ориентированном языке.

С перегрузкой, каждый класс объектов работают как примитивные типы, которые делают занятия более естественно использовать, так же просто, как 1 + 2.

Say сложный номер класса, комплекс. Комплекс (1,2i) + Complex (2,3i) дает комплекс (3,5i). 5 + Комплекс (3, 2i) дает комплекс (8, 2i). Комплекс (2, 4i) + -1,8 дает комплекс (0,2, 4i).

Это намного проще в использовании. Если нет перегрузки оператора, вы должны использовать кучу методов класса для обозначения «добавить» и сделать нотацию неуклюжей.

Перегрузка оператора должна быть тщательно определена; в противном случае возникает путаница. Например, оператор «+» естественным образом добавляет числа, время, дату или конкатенацию массива или текста. Добавление оператора «+» к классу мыши или автомобиля может не иметь никакого смысла. Иногда некоторые перегрузки могут показаться неестественными для некоторых людей. Например, Array (1,2,3) + Array (3,4,5). Некоторые могут ожидать Array (4,6,8), но некоторые ожидают Array (1,2,3,3,4,5).

Смежные вопросы