2012-02-26 2 views
0

Из http://www.learncpp.com/cpp-tutorial/97-overloading-the-increment-and-decrement-operators/реализации префикса оператора ++

декларации класса

class Digit 
{ 
private: 
    int m_nDigit; 
public: 
    Digit(int nDigit=0) 
    { 
     m_nDigit = nDigit; 
    } 

    Digit& operator++(); 
    Digit& operator--(); 

    int GetDigit() const { return m_nDigit; } 
}; 

Их реализация operator++

Digit& Digit::operator++() 
{ 
    // If our number is already at 9, wrap around to 0 
    if (m_nDigit == 9) 
     m_nDigit = 0; 
    // otherwise just increment to next number 
    else 
     ++m_nDigit; 

    return *this; 
} 

Мой альтернативной реализации operator++

Digit& Digit::operator++() 
{ 
    return Digit(m_nDigit == 9 ? 0 : (m_nDigit + 1)); 
} 

Я хотел бы знать

  1. , если есть какие-либо недостатки создания нового объекта, как я сделал, и
  2. о том, как выбрать одну из этих реализаций?
+1

Ваша альтернативная реализация выглядит так, будто ей не хватает '='. –

+1

@CarlNorum: исправлено, извините, что goofup. – Lazer

ответ

3

В вашей реализации альтернативных у вас есть 2 проблемы:

  1. вместо m_nDigit = 9 сделать m_nDigit == 9. В настоящее время m_nDigit всегда будет 9, а возвращаемое значение всегда будет 0.

  2. Вы должны изменить значение m_nDigit. При возвращении 0 - нет.

Оператор возврата является проблематичным, поскольку ожидается, что оператор изменит значение операнда, а не создает новый объект.

редактировать

Для выяснения вопроса, рассмотрим код:

Digit x; 
x++; 

Что бы ожидать x быть как результат этого кода? Я ожидаю, что это будет 1. Используя вашего оператора, он останется без изменений.

+0

Я обновил вопрос. В чем проблема, если он создает новый объект? – Lazer

+0

@Lazer, вы можете делать все, что хотите, но создание нового объекта на самом деле не соответствует нормальной семантике оператора prefix '++'. –

+0

@Lazer - проблема - это ожидания, когда кто-то называет этого оператора. Когда у меня есть код типа 'Digit x; x ++; '- что должно случиться, как вы думаете? – littleadv

4

Там, конечно, и отрицательные стороны создания объекта, как вы сделали:

  1. Это не будет компилировать. Невозможно привязать неконстантную ссылку на временную.

  2. Даже если он сделал компилировать не будет выполнять правильную работу (ваша версия делает operator++ установить m_nDigit в 9, другие приращения версии m_nDigit, обтекание, когда 10 достигается).

  3. Даже если он скомпилировал и сделал правильные вещи, это было бы очень опасно. Возвращенная ссылка будет привязана к временному объекту, который будет уничтожен до возвращения функции, это будет означать, что любая попытка доступа к объекту, на который ссылается возвращаемое значение operator++, приведет к неопределенному поведению.

Чтобы выбрать между двумя реализациями, вы должны выбрать тот, который скомпилирован, является правильным и безопасным.

2
  1. m_nDigit = 9 - это присвоение и всегда будет оцениваться как true.
  2. Вы возвращаете копию объекта, но возвращаемый тип является ссылкой. Это может вас укусить (см. Is returning a temp-object by reference possible).
  3. Почему не m_nDigit = (m_nDigit + 1) % 9;?
4

У вас возникла проблема с тройным оператором. Также вы возвращаете копию объекта, а не сам объект, и если вы пытаетесь перегрузить оператор для работы как встроенный тип, вы всегда должны возвращать ссылку на объект.

Я думаю, что вы должны сделать это так:

Digit& Digit::operator++() 
{ 
    m_nDigit = (m_nDigit == 9 ? 0 : m_nDigit++); 
    return *this; 
} 

Или так:

Digit& Digit::operator++() 
{ 
    m_nDigit = (++m_nDigit % 10); 
    return *this; 
} 

Минусом создания нового объекта является то, что в такой код:

Digit d; 
++d; 

Я бы ожидал, что значение d изменится, а с новым объектом - нет. Этот оператор во многих случаях используется как это (без присвоения ему переменной), поэтому, если вы не увеличиваете и не возвращаете один и тот же объект, вы не можете использовать его таким образом.

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