Перегрузка оператора для сложного разыменования и назначения - PullRequest
1 голос
/ 28 мая 2019

С перегрузками операторов C ++ можно создать класс, который эмулирует тип указателя, поэтому я экспериментировал с абстрагированием FILE операций чтения с этим подходом.

class FilePointer
{
    FILE* file;
    size_t position;
    FilePointer (FILE* file, size_t position)
    {
        this->file = file;
        this->position = position;
    };
    public:
    FilePointer (FILE* file)
    {
        this->file = file;
        this->position = 0;
    };
    FilePointer operator+ (size_t offset)
    {
        return FilePointer(file,position + offset);
    };
    FilePointer operator++ () // Prefix : ++FilePointer
    {
        position++;
        return *this;
    };
    FilePointer operator++ (int) // Postfix : FilePointer++
    {
        FilePointer before = *this;
        position++;
        return before;
    };
    FilePointer operator+= (size_t offset)
    {
        position += offset;
        return *this;
    };
    uint8_t operator* ()
    {
        fseek(file,position,SEEK_SET);
        Uint8 out;
        fread(&out,1,1,file);
        return out;
    };
    uint8_t operator[] (size_t offset)
    {
        return *(*this + offset);
    };

};

Как видно из приведенного выше фрагмента кода, мне удалось выяснить, как различать вариации оператора приращения, чтобы данные FilePointer f; f++ и ++f вели себя интуитивно.

Что если я захочу использовать этот класс для файла пишет ? В настоящее время я могу получить байт uint8_t something = f[0];, и это работает, но если я хочу что-то «установить», то есть f[0] = 100;, перегрузки, как они есть, не будут работать для этого.

Помимо того, является ли это "хорошей практикой" (хотя и не стесняйтесь об этом думать), есть ли способ реализовать это поведение в перегрузках операторов для класса?

uint8_t n = f[0];
n++;
f[0] = n;

Или, если подумать, что-то вроде этого:

f[1]++;

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

Ответы [ 2 ]

2 голосов
/ 28 мая 2019

Один способ, которым я могу представить, - это реализовать еще один класс, который представляет «разыменованный FilePointer»

Это практически единственный способ сделать это. Это был бы объект «прокси-типа», который можно преобразовать в uint8_t (возможно, неявно в подобном случае, хотя в целом я не хочу неявных преобразований), но также можно назначить.

Он должен был бы быть создан с FilePointer* и friend, чтобы он мог вызывать соответствующую функцию «записи».

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

Также чтение по одному байту за раз - это sloooooow.

В целом, хотя ваша попытка достойна восхищения, я бы посоветовал против подхода в целом. Вы можете, по крайней мере, обернуть FILE* в хороший класс, который делает для вас fclose, если он выходит из области видимости.

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

Я так не думаю. Для того, чтобы вы вернулись из operator[], нужно какое-то магическое состояние, которое может принять значение для «установки» и подключения к машине FILE*. Возвращение uint8_t просто никогда не позволит вам сделать это.

0 голосов
/ 28 мая 2019

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

Одна вещь, о которой следует знать при использовании прокси-подхода, это то, что вызывающая сторона может удерживать несколько прокси-объектов, используя auto или auto&, и пытаться обновить их не по порядку. Я не думаю, что есть эффективный способ решить эту проблему.

А как насчет operator --? Хотя библиотека c ++ имеет концепцию односторонних итераторов. может быть, итераторы - лучшая метафора?

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