Вопрос о перегруженном операторе < - PullRequest
3 голосов
/ 19 сентября 2011

Попытка изучить шаблоны функций C ++.Как часть которого у меня есть этот код ниже.Это работает нормально, но у меня есть вопросы, как показано ниже: -

1] Почему оператор << перегружающей функции должен быть другом?Если я удаляю ключевое слово friend, это выдает ошибку компиляции, говорящую: operator << имеет слишком много параметров. </p>

2] Почему перегружающая функция operator << должна возвращать ссылку на объект ostream, который также является входным аргументомк этому?</p>

3] Я сомневаюсь в этом, но имеют ли эти два вопроса какое-либо отношение к тому факту, что шаблоны функций используются для определенного пользователем класса, который имеет перегруженные функции?

template <class T>
T Average(T *atArray, int nNumValues)
{
    T tSum = 0;
    for (int nCount=0; nCount < nNumValues; nCount++)
        tSum += atArray[nCount];

    tSum /= nNumValues;
    return tSum;
}

class Cents
{
private:
    int m_nCents;
public:
    Cents(int nCents)
        : m_nCents(nCents)
    {
    }

    //Why is friend needed below

    //Why does it need to return ostream&, why can't it have void return type, as all it is doing is printing the class private member.
    friend ostream& operator<< (ostream &out, const Cents &cCents)
    {
        out << cCents.m_nCents << " cents ";
        return out;
    }

    /* 
    void operator <<( const Cents &cCents) //did not work - compilation errors
    {
        cout << cCents.m_nCents << " cents ";
    }
    */

    void operator+=(Cents cCents)
    {
        m_nCents += cCents.m_nCents;
    }

    void operator/=(int nValue)
    {
        m_nCents /= nValue;
    }
};

int main()
{
    int anArray[] = { 5, 3, 2, 1, 4 };
    cout << Average(anArray, 5) << endl;

    double dnArray[] = { 3.12, 3.45, 9.23, 6.34 };
    cout << Average(dnArray, 4) << endl;

    Cents cArray[] = { Cents(5), Cents(10), Cents(15), Cents(14) };
    cout << Average(cArray, 4) << endl;

    cin.get();
    return 0;
}

Ответы [ 3 ]

3 голосов
/ 19 сентября 2011

Почему оператор << функции перегрузки должен быть другом?Если я удаляю ключевое слово friend, это выдает ошибку компиляции, говоря: operator << имеет слишком много параметров. </p>

<< изменяет состояние потока, и, следовательно, в идеале он должен быть реализован как член его левого операндатип.Однако его левые операнды являются потоками из стандартной библиотеки, и хотя большинство операторов вывода и ввода потока, определенных стандартной библиотекой, действительно определены как члены классов потоков, при реализации операций вывода и ввода для ваших собственных типов выне может изменить типы потоков стандартной библиотеки.
Вот почему вам нужно реализовать эти (<< и >>) операторы для ваших собственных типов как функции, не являющиеся членами.Поскольку вам необходимо получить доступ к закрытым / защищенным переменным-членам вашего объекта класса внутри определения оператора, эти перегруженные операторы необходимо объявить в качестве друга вашего класса.

Почему оператор << перегружаетфункция должна возвращать ссылку на объект ostream, который также является входным аргументом для него? </p>

Возврат ссылки на стандартный объект потока позволяет иметь Object Chaining .

У вас могут быть такие вызовы, как:

out<<obj1<<obj2;

Шаблоны используются для определенного пользователем класса, который имеет перегруженные функции?

Шаблоны помогают реализовывать универсальные функции и классы, которые могут вызываться для разных типов данных, а компилятор заботится о генерации кода для этих конкретных типов данных.Таким образом, два вышеуказанных пункта не связаны между собой.


Настоятельно рекомендуем прочитать этот раздел часто задаваемых вопросов:
Перегрузка оператора

1 голос
/ 19 сентября 2011

[1] Он должен быть другом, потому что пытается получить доступ к закрытой переменной-члену m_nCents, которая доступна только для функций-членов Cents или для друзей Cents.

[2] Это стандартная сигнатура функции для перегрузки «потоковых операторов». Это позволяет объединять << s:

out << a << b;

, что эквивалентно

(out << a) << b;

РЕДАКТИРОВАТЬ: Кажется, вы хотите, чтобы operator<< был членом класса. Это невозможно, поскольку его первый операнд - ostream, а не Cents. friend фактически объявляет его как функцию, не являющуюся другом. Если вы оставите ключевое слово friend, вы объявите его как функцию-член (так как оно находится внутри определения класса), но в этом случае у него слишком много аргументов (два в сигнатуре и неявный Cents в качестве первого аргумента). тот, который вызывается, указатель this, если хотите).

Объявление operator<< для потоковой передачи как функции, не являющейся членом, является стандартным способом сделать это, либо friend, либо нет (зависит от того, требуется ли вам friend, или вы делаете m_nCents общедоступным как-то).

0 голосов
/ 19 сентября 2011

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

Например:

Cents a,b,c;
cout << a << b << c;

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

Позвольте мне расширить эту концепцию.Приведенный выше пример эквивалентен следующему:

op(op(op(cout,a),b),c);

Где 'op' - это сокращенное обозначение фактического имени функции перегруженного оператора.Обратите внимание, что он не вызывается для экземпляра Cents и на самом деле не будет иметь this ptr, потому что он существует вне класса, как автономная функция.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...