перегрузка оператора << в c ++ - PullRequest
2 голосов
/ 04 октября 2010

эй, у меня есть кое-что, что я не могу понять, есть два типа решений для перегрузки: этот оператор 1 включает друга в начале метода, а другой 1 - без друга Мне бы очень хотелось, чтобы кто-нибудь объяснил, в чем разница между их достоинствами и недостатками. например перегрузка оператора << в классе рациональный: </p>

class Rational:
{
    private: int m_t,m_b;
    ...
    friend ostream& operator<<(ostream& out,const Rational& r) // option 1
    { return out << r.m_t << "/" <<r.m_b;}  // continue of option 1

    ostream& operator<<(ostream& out,const Rational& r){return r.print();} // option 2
    virtual ostream& print(ostream& out) const // continue of option 2
    { //
      return out<<m_t << "/" << m_b;
    } //
};

Мне сказали, что второй вариант не верен, если кто-то может исправить меня, я бы очень его оценил. заранее спасибо.

Ответы [ 3 ]

4 голосов
/ 04 октября 2010

Краткий ответ: Вариант № 2 на самом деле не опция, а синтаксическая ошибка, потому что он пытается определить бинарный оператор как член, передающий два операнда.

Несколько более длинный ответ: если вы сделаете второй операнд свободной функцией (не членом класса), это сработает.Какой из них предпочтительнее, зависит от обстоятельств и ваших предпочтений.Для начала: недостатком первого является то, что он позволяет operator<< получать доступ ко всему в Rational (включая частные вспомогательные функции), а недостатком второго является то, что вы вводите функцию в публичный API класса, который никому не нужен,

2 голосов
/ 04 октября 2010

operator<< (для ostream) должна быть свободной функцией (поскольку левый аргумент является потоком, а не вашим классом).

Ключевое слово friend делает его бесплатной функцией (бесплатной функцией, которая имеет доступ к закрытым членам).

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

class Rational:
{
    private: int m_t,m_b;
    public:
    ...
    virtual ostream& print(ostream& out) const
    { 
      return out<<m_t << "/" << m_b;
    } 
};

ostream& operator<<(ostream& out,const Rational& r)
{
    return r.print(out);
}
0 голосов
/ 04 октября 2010

Рассмотрим функцию, которая должна выводить num и den Rational:

ostream& operator<<(ostream& out, const Rational& r)
{
    return out;
}

К сожалению, это всего лишь глобальная функция.Как и любая другая глобальная функция, она не может получить доступ к закрытым членам Rational.Чтобы заставить его работать с Rational объектами, необходимо сделать его friend из Rational:

class Rational
{
    private: int m_t,m_b;

    // ...

    friend ostream& operator<<(ostream& out, const Rational& r);
};

ostream& operator<<(ostream& out, const Rational& r)
{
    out << r.m_t << "/" <<r.m_b;
    return out;
}

friend ostream& operator<<(ostream& out, const Rational& r); внутри Rational класса указывает, что функция ostream& operator<<(ostream& out, const Rational& r) может напрямую использоватьЛичные члены Rational.

Теперь, когда вы пишете:

Rational r(1, 2);  // Say, it sets num and den
cout << r;

, выполняется следующий вызов функции:

operator<<(cout, r);

Можете ли вы написать operator<<как функция-член Rational?Это просто невозможно из-за вышеуказанного преобразования, где cout должен быть первым параметром.Если вы сделаете operator<< членом Rational:

class Rational
{
    private: int m_t,m_b;

    // ...

    public:

    ostream& operator<<(ostream& out) const
    {
        out << r.m_t << "/" <<r.m_b;
        return out;
    }
};

, вам нужно назвать его так:

Rational r(1, 2);
r.operator<<(cout);

, что ужасно.

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