Можно ли переопределить оператор доступа к массиву для указателей на объект в C ++? - PullRequest
0 голосов
/ 27 августа 2009

Я пытаюсь провести некоторый рефакторинг кода и столкнулся с проблемой. В программе есть менеджер данных, который возвращает указатели на массивы структур как пустоту *. Один из новых типов данных вместо одного указателя на массив структур имеет два указателя на массивы чисел. Проблема состоит в том, что весь код обработки выполняется путем доступа к массиву [index] .qwTimestamp и массиву [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] и, таким образом, указывает на случайную память.

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

Ответы [ 2 ]

9 голосов
/ 27 августа 2009

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

0 голосов
/ 27 августа 2009

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

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

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