Использование * это хорошая идея? - PullRequest
3 голосов
/ 25 июня 2009

Я не уверен, если

return *this

это единственный способ вернуть экземпляр класса, который вызвал функцию-член? Причина, по которой я спросил, состоит в том, что наш инструктор сказал нам избегать использования указателей в случае необходимости, и мне интересно, если это единственный случай, когда единственный необходимый способ сделать это - вернуть указатель this.

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

Fraction C = A.plus(B);

плюс функция-член определяется следующим образом:

Fraction& plus( const Fraction frac )

Инструктор хочет, чтобы мы делали C = A + = B, поэтому я думаю, что именно поэтому.

Ответы [ 7 ]

7 голосов
/ 25 июня 2009

Получить нового инструктора. Похоже, что объявление plus () совершенно неверно.

  • вероятно, оно должно возвращать значение, а не ссылку
  • если он должен вернуть ссылку, он должен вернуть константную ссылку
  • это определенно должно принимать константную ссылку в качестве параметра

Это для вероятных разумных реализаций функции-члена plus (). Конечно, это должен быть друг.

2 голосов
/ 25 июня 2009

Я думаю, что в этом случае безопасно использовать

return *this

потому что this относится к текущему объекту, поэтому он гарантированно существует, поэтому он не будет нулевым.

Причина, по которой plus возвращает ссылку на себя, заключается в том, что она может быть связана:

Fraction C = A.plus(B).plus(D) // perhaps?

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

Не будет ли плюс принимать ссылку вместо копирования параметра?

Fraction& plus( const Fraction& frac )

Это похоже на реализацию operator= (пример):

  A& operator=(const A& right) {
    if(this == &right) return *this;    // Handle self-assignment
    b = right.b;
    return *this;
  }

Возможно, вы не захотите изменять объект и возвращать новый объект:

// assuming there's a constructor Fraction(int numerator, int denominator):
Fraction* plus(Fraction const& rhs)
{
    return new Fraction(numerator * rhs.denominator
                        + rhs.numerator * denominator,
                        denominator * rhs.denominator);
}

Но это, конечно, должно возвращать указатель на новый экземпляр, который не является ссылкой, как, возможно, требуется в вашей задаче (?).

Или даже лучше:

Fraction plus(Fraction const& rhs)
{
    return Fraction(numerator * rhs.denominator
                    + rhs.numerator * denominator,
                    denominator * rhs.denominator);
}

Это создаст Fraction в пространстве вызывающей функции, так что нет никаких затрат на копирование структуры при возврате.

1 голос
/ 25 июня 2009

Нет ничего плохого в возврате *this. Например, так должны работать перегрузки модифицирующих операторов. Кажется, что метод plus на самом деле является просто способом предоставления оператора + = для вашего класса без фактической перегрузки оператора (я предполагаю, что вы еще не дошли до перегрузки операторов), поэтому возвращение *this в этом случае является обычным поведением .

1 голос
/ 25 июня 2009

Да, это единственный способ. Единственный способ получить доступ к текущему объекту в методе - через него, и это указатель.

Это нормально, и это общепринятая практика.

0 голосов
/ 25 июня 2009

наш инструктор сказал нам избегать использования указателей при необходимости

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

Лично я никогда не вызываю методы и не обращаюсь к членам через this. То есть я НЕ делаю следующее:

class A {
    public:
    int x;
    int get_x()
    {
        return this->x;
    }

    int get_x_plus_5()
    {
        return this->get_x() + 5;
    }
}

Тем не менее, я в порядке с возвращением *this.

Ваш инструктор, вероятно, пытается заставить вас избежать (1) возврата указателей на объекты в стеке из функций (что означает, что они не будут существовать после выхода из функции) и (2) размещения объектов в свободном хранилище, когда тебе не нужно this не страдает ни от одной из этих проблем.

0 голосов
/ 25 июня 2009

Я считаю, что семантика должна заключаться в том, что функция-член «плюс» возвращает «новый» объект, который представляет сумму звонящего и вызываемого. примечание :: новый не означает «новое» ключевое слово в C ++ :) так что для вашего примера,

// the constructor accepts (numerator, denominator).
// in your case, the caller object would be A, and the called object would be B(other).
return Fraction(numerator * other.denominator + other.numerator * denominator, denominator * other.denominator);

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

Чтобы уточнить, это должна быть ваша подпись "плюс",

Fraction plus( const Fraction& frac );

ни на вызывающего абонента, ни на вызываемого не должно быть положительного.

0 голосов
/ 25 июня 2009

В вашем методе plus() вы, вероятно, должны создать новый объект Fraction и вернуть его вместо изменения текущего, а затем вернуть *this. Вы, вероятно, не хотите менять A на A.plus(B). Чтобы вернуть новый Fraction, подпись plus() лучше всего будет:

Fraction plus(const Fraction &frac);

(Если вы не изменяете this в методе plus(), почему вы хотите вернуть *this?)

...