【问题标题】:Is it possible to override the array access operator for pointers to an object in C++?是否可以覆盖指向 C++ 中对象的指针的数组访问运算符?
【发布时间】:2009-08-27 16:11:10
【问题描述】:

我正在尝试对代码进行一些重构,但遇到了问题。该程序有一个数据管理器,它以 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

当 tmp[1] 被调用时,C++ 正在索引指针,因此指向随机内存。

是否有可能重写 C++ 索引对象指针的方式,或实现相同目标的其他机制?

【问题讨论】:

  • 任何以双下划线开头的标识符都是标准保留的。不要使用'__int32'等。见stackoverflow.com/questions/228783/…
  • 该程序将在VS2008,Windows only环境中使用,因此它不严格符合标准。但了解未来是件好事。
  • @Martin 为实施标准保留。 __int32 等是 MS 实现的一部分,因此完全可以使用,只要可移植性不是问题。
  • @bsruth 如果您正在为 Windows 构建,请使用 MinGW 并且不要使用 __int64 而是 long long。 GCC在遵循标准方面更好

标签: c++ pointers operators operator-overloading


【解决方案1】:

不,这是不可能的 - 指针被认为是内置类型,因此不能使其运算符重载。但是,您当然可以 创建智能指针类(类似于指针但具有附加功能的类)并重载它们的运算符 - 例如,看看你的编译器对 std::auto_ptr 的实现。

【讨论】:

  • 我同意这一点,创建自己的“指针”类并在其上重载数组访问。您还可以在原始类上重载“address-of”运算符以返回您的自定义指针。
【解决方案2】:

先尝试解引用指针:

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

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

【讨论】:

  • 不幸的是,这不起作用,因为所有其他处理函数都需要一个真实的记录数组。我必须为这个对象设置一个特殊情况,这是我试图避免的。
猜你喜欢
  • 2015-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-18
  • 2011-05-09
相关资源
最近更新 更多