vector/array 仅在声明定义时进行边界检查

vector/array bounds check only when a define is declared

我已经创建了我自己的容器,它是从矢量继承的。我想以一种检查由 #define 决定的边界的方式重新实现 operator[]

所以举个例子,忽略模板参数,因为它们很复杂而且无关紧要

class MyArray : vector<double>
{
    //...
    virtual double& operator[](const size_type& index);
    virtual const double& operator[](const size_type& index) const;
    //...
}


double& MyArray::operator[](const size_type& index)
{
    #ifdef DEBUG_ENABLED
        return this->at(index);
    #else
        return (*this)[index];
    #endif
}

但是,这不起作用,因为 operator[] 已过载,在 #else 处调用 operator[] 将变为递归。

我想根据我的#define 检查边界,而不是根据我使用的是 std::vector<>::at() 还是 std::vector<>::operator[]

我该如何解决?

编辑:因为它提供了很多使用 std::vector 作为成员而不是继承的方法,所以我不得不提到这样做对我来说不是一个好的解决方案,因为我必须重新实现所有std::vector 的成员函数。这样做可不是一件愉快的事!

首先,从标准容器派生并不是一个好主意,因为它们缺少适当支持用作基础的功能(例如虚拟析构函数)class。标准容器的目的是它们不会被用作基础。

如果您必须这样做,请添加此内容;

class MyArray : vector<double>
{
    //   all your other stuff

    typedef vector<double> Base;

};

double& MyArray::operator[](const size_type& index)
{
    #ifdef DEBUG_ENABLED
        return this->at(index);
    #else
        return (*((Base *)this))[index];
    #endif
}

通常认为使用 static_cast 可以更好地完成函数中的类型转换,但您明白了。

最好让容器成为你的成员class,运算符函数的各种成员转发给被包含的成员

class MyArray
{
    //   all your other stuff

   private:
       std::vector<double> data;


};

double& MyArray::operator[](const size_type& index)
{
    #ifdef DEBUG_ENABLED
        return data.at(index);
    #else
        return data[index];
    #endif
}

最后,无论哪种方式,operator[]() 都不需要是虚拟的。

只需根据需要调用基础class成员函数:

double& operator[](size_type index)
{
    #ifdef DEBUG_ENABLED
        return std::vector<double>::at(index);
    #else
        return std::vector<double>::operator[](index);
    #endif
}

您也应该提供一个 const 版本。另请注意,您可能不想让此运算符 virtual.

"Since it's offered a lot to use std::vector as a member instead of inheriting, I have to mention that doing that isn't a good solution for me because i'll have to reimplement ALL the member functions of std::vector. That's not so pleasant to do!

您不必这样做。我这里使用了继承来减轻压力。

#include <iostream>
#include <vector>

using namespace std;

template <typename T>
class Vector_ : private vector<T>
{
public:
    virtual ~Vector_(){}
    virtual const T& operator[](const size_t index);
    virtual const T& at(const size_t index);
};

/*
<<I would like to make the check for bounds based on my #define, and  not based on
std::vector<>::at() or std::vector<>::operator[]. >>
*/
template <typename T>
const T& Vector_<T>::operator[](const size_t index)
{
#ifdef DEBUG_ENABLED
    return (*((vector<T>*)this))->at(index)
#else
    return (*((vector<T> *)this))[index];
#endif
}   
template <typename T>
const T& Vector_<T>::at(const size_t index)
{
#ifdef DEBUG_ENABLED
    return (*((vector<T>*)this))->at(index)
#else
    return (*((vector<T>*)this))[index];
#endif
}

//test...
Vector<int>_ vec;
vec.push_back(3);

vec[2]; or vec.at(2); //no exception

#define DEBUG_ENABLED
vec[2]; or vec.at(2);  //exception