Оператор перегрузки << для печати в качестве члена - PullRequest
6 голосов
/ 12 декабря 2011

Есть ли способ перегрузить оператор <<, как член класса, для печати значений в виде текстового потока. Такие как: </p>

class TestClass {
public:
    ostream& operator<<(ostream& os) {
        return os << "I'm in the class, msg=" << msg << endl;
    }

private:
    string msg;
};


int main(int argc, char** argv) {
    TestClass obj = TestClass();
    cout << obj;

    return 0;
}

Единственный способ, которым я мог придумать, это перегрузить оператор вне класса:

ostream& operator<<(ostream& os, TestClass& obj) {
    return os << "I'm outside of the class and can't access msg" << endl;
}

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

Любые комментарии или рекомендации о том, как действовать, были бы полезны:)

Ответы [ 6 ]

9 голосов
/ 12 декабря 2011

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

class TestClass {
public:
    friend ostream& operator<<(ostream& os, TestClass const & tc) {
        return os << "I'm a friend of the class, msg=" << tc.msg << endl;
    }

private:
    string msg;
};
6 голосов
/ 12 декабря 2011

Я полагаю, что одним из популярных способов сделать это является отсутствие 1001 *, не являющегося членом, не являющимся другом, которое вызывает открытый не виртуальный метод print в вашем классе.Этот метод печати может выполнять работу или делегировать защищенную виртуальную реализацию.

class TestClass {
public:
    ostream& print(ostream& os) const {
        return os << "I'm in the class, msg=" << msg << endl;
    }

private:
    string msg;
};


ostream& operator<<(ostream& os, TestClass& obj) {
    return obj.print(os);
}

int main(int argc, char** argv) {
    TestClass obj;
    cout << obj;

    return 0;
}
5 голосов
/ 12 декабря 2011

Вы наткнулись на канонический способ реализации этой функциональности. То, что у вас есть, правильно.

1 голос
/ 12 декабря 2011

Вы можете сделать его членом класса, который находится слева от <<, который в вашем случае равен ostream.

Что вы можете сделать, так это иметь базовый класс сvoid do_stream(ostream& o); участник для всех ваших сообщений и не входящих operator<<, которые бы назвали его.

0 голосов
/ 12 декабря 2011

Вы должны сделать его не членом (поскольку первый параметр не является вашим классом).

Но вы можете написать это в своем определении класса (как друг):

class TestClass
{
public:
    // Have a nice friend.
    // This tightly binds this operator to the class.
    // But that is not a problem as in reality it is already tightly bound.
    friend ostream& operator<<(ostream& os, TestClass const& data)
    {
        return os << "I'm in the class, msg=" << data.msg << endl;
    }

private:
    string msg;
};

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

0 голосов
/ 12 декабря 2011

Вы правы, это единственный способ реализовать оператор потока - вне класса.

Вам необходимо объявить метод как friend.

Вот как это делается.

...