Можно ли это сделать без помощи друзей?

Можно ли преобразовать следующий код (я сохранил только соответствующую часть) для использования статической функции-члена, а не функции, свободной от друзей? Если нет, то почему нет? Я пытался преобразовать его для использования статической функции-члена несколькими различными способами и потерпел неудачу (продолжал получать разные ошибки компилятора для разных вариантов), но я понял из ответа на этот вопрос, что вы можете использовать любой из них для того же. Разве это не технически верно из-за некоторого свойства синтаксиса C++? Куда я здесь не так?

class Tape {
    public:
        friend std::ostream &operator<<(std::ostream &, Tape &);

    private:
        char blank;
        size_t head;
        std::string tape;
}


std::ostream &operator<<(std::ostream &out, Tape &tape) {
    out << tape.tape << std::endl;
    for (size_t i = 0; i < tape.head; i++)
        out << ' ';
    out << '^' << std::endl;
    return out;
}

2 ответа

Решение

Согласно стандарту C++

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

Таким образом, вы не можете определить operator << как статическая функция mamber класса. Тем не менее, внутри определения оператора вы можете использовать статические функции-члены. Например

#include <iostream>

class A
{
private:
    int x = 10;
public:
    static std::ostream & out( std::ostream &os, const A &a )
    {
        return ( os << a.x );
    }
};

std::ostream & operator <<( std::ostream &os, const A &a )
{
    return ( A::out( os, a ) );
}

int main() 
{
    A a;
    std::cout << a << std::endl;

    return 0;
}

Напротив C++ в C# операторские функции определены как статические.:)

Так как std::ostream Аргумент является левой частью оператора, он не может быть членом вашего класса (статическим или иным).

Так что это должна быть бесплатная функция, потому что вы не можете добавлять участников в std::ostream,

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

class Tape {
    public:
    void print(std::ostream &out) const 
    {
        out << tape << std::endl;
        for (size_t i = 0; i < head; i++)
            out << ' ';
        out << '^' << std::endl;
    }
};


std::ostream& operator<<(std::ostream &out, const Tape &tape) 
{
    tape.print(out);
    return out;
}
Другие вопросы по тегам