Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Можно ли переопределить оператор доступа к массиву для указателей на объект в С++?

Автор вопроса: bsruthОтветов: 2

Я пытаюсь сделать рефакторинг кода и столкнулся с проблемой. В программе есть менеджер данных, который возвращает указатели на массивы структур как void*. Один из новых типов данных вместо одного указателя на массив структур имеет два указателя на массивы чисел. Проблема в том, что весь код обработки выполняется путем доступа к array[index].qwTimestamp и array[index].snSample, которые являются общими для всех типов записей.

Я думал, что переопределение оператора доступа к массиву ( [] ), как показано ниже, может решить проблему:

class ADRec {

public:
    ADRec(unsigned __int64* ts, __int32* data, unsigned index = 0): mTimestamps(ts), mDataPoints(data), mIndex(index) {

        qwTimeStamp = mTimestamps[mIndex];
        snSample = mDataPoints[mIndex];

    }
    ADRec operator[](unsigned i) {
        return ADRec(mTimestamps, mDataPoints, i);

    }
    unsigned __int64 qwTimeStamp;
    __int32 snSample;

private:
    unsigned __int64* mTimestamps;
    __int32* mDataPoints;
    unsigned mIndex;
};

Этот подход отлично работает, если вы используете объект:

unsigned __int64 ts[] = { 2, 3, 4, 5};
__int32 data[] = {4, 6, 8, 10};

ADRec tmp =  ADRec(ts, data, 0);

ASSERT(tmp[0].qwTimeStamp == 2);
ASSERT(tmp[0].snSample == 4);
ASSERT(tmp[1].qwTimeStamp == 3);
ASSERT(tmp[1].snSample == 6);

Но не работает, если вы используете указатель на объект:

unsigned __int64 ts[] = { 2, 3, 4, 5};
__int32 data[] = {4, 6, 8, 10};

ADRec* tmp =  new ADRec(ts, data, 0);

ASSERT(tmp[0].qwTimeStamp == 2);
ASSERT(tmp[0].snSample == 4);
ASSERT(tmp[1].qwTimeStamp == 3); //fails
ASSERT(tmp[1].snSample == 6); //fails

C++ индексирует указатель при вызове tmp[1] и, таким образом, указывает на случайную память.

Можно ли переопределить способ, которым С++ индексирует указатель на объект, или какой-либо другой механизм, который позволит достичь той же цели?

  • Любой идентификатор, начинающийся с двойного подчеркивания, зарезервирован стандартом. Не используйте '__int32' и т. д. См. stackoverflow.com/questions/228783/ Martin York 27.08.2009
  • Эта программа будет использоваться в VS2008, только в среде Windows, поэтому она не соответствует строго стандарту. Но это полезно знать на будущее. bsruth 27.08.2009
  • @Martin Зарезервировано стандартом ДЛЯ РЕАЛИЗАЦИИ. __int32 и др. являются частью реализации MS, поэтому их вполне можно использовать, если переносимость не является проблемой. 27.08.2009
  • @bsruth Если вы создаете для Windows, используйте MinGW и не __int64, а long long. GCC лучше следует стандарту user877329 28.03.2012

c++operatorspointersoperator-overloading

Ответы

Ответ 1 · рейтинг 9 · Community

Нет, это невозможно - указатели считаются встроенными, поэтому их операторы не могут быть перегружены. Однако вы, безусловно, можете создавать классы интеллектуальных указателей (классы, которые действуют как указатели, но с дополнительными возможностями) и перегружать их операторы - взгляните, например, на реализацию std::auto_ptr в вашем компиляторе.

Ответ 2 · Darryl

Сначала попробуйте разыменовать указатель:

ADRec* tmp =  new ADRec(ts, data, 0);

ASSERT(tmp[0][1].qwTimeStamp == 3);
// or
ASSERT((*tmp)[1].qwTimeStamp == 3);

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы