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
我已经创建了我自己的容器,它是从矢量继承的。我想以一种检查由 #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