运算符 过载
是否可以重载[]
运算符两次? 允许,就像这样: function[3][3]
(就像在一个二维数组中)。
如果可能的话,我想看一些示例代码。
你可以重载operator[]
来返回一个你可以再次使用operator[]
的对象来获得结果。
class ArrayOfArrays { public: ArrayOfArrays() { _arrayofarrays = new int*[10]; for(int i = 0; i < 10; ++i) _arrayofarrays[i] = new int[10]; } class Proxy { public: Proxy(int* _array) : _array(_array) { } int operator[](int index) { return _array[index]; } private: int* _array; }; Proxy operator[](int index) { return Proxy(_arrayofarrays[index]); } private: int** _arrayofarrays; };
那么你可以像这样使用它:
ArrayOfArrays aoa; aoa[3][5];
这只是一个简单的例子,你想添加一些边界检查和东西,但你明白了。
expression式x[y][z]
要求x[y]
求值到支持d[z]
的对象d
。
这意味着x[y]
应该是一个带有operator[]
的对象,该对象的计算结果是也支持operator[]
的“代理对象”。
这是链接他们的唯一方法。
或者,重载operator()
以获取多个参数,以便可以调用myObject(x,y)
。
如果您在first []调用中返回某种代理类,则可能是这样。 不过,还有其他的select:你可以重载operator(),它可以接受任意数量的参数( function(3,3)
)。
对于二维数组,具体来说,您可能会得到一个单一的运算符[]重载,该重载返回指向每一行的第一个元素的指针。
然后,您可以使用内置索引运算符来访问行内的每个元素。
一种方法是使用std::pair<int,int>
:
class Array2D { int** m_p2dArray; public: int operator[](const std::pair<int,int>& Index) { return m_p2dArray[Index.first][Index.second]; } }; int main() { Array2D theArray; pair<int, int> theIndex(2,3); int nValue; nValue = theArray[theIndex]; }
当然,你可以typedef
pair<int,int>
您可以使用代理对象,如下所示:
#include <iostream> struct Object { struct Proxy { Object *mObj; int mI; Proxy(Object *obj, int i) : mObj(obj), mI(i) { } int operator[](int j) { return mI * j; } }; Proxy operator[](int i) { return Proxy(this, i); } }; int main() { Object o; std::cout << o[2][3] << std::endl; }
你知道什么function
, function[x]
和function[x][y]
是什么意思?
首先看看function
的定义。 也许有一些声明或定义像
SomeClass function;
(因为你说这是运算符重载,我想你不会像SomeClass function[16][32];
那样感兴趣SomeClass function[16][32];
)
所以function
是SomeClass
types的一个实例。 然后,查看SomeClass
声明,以获得operator[]
重载的返回types,就像
ReturnType operator[](ParamType);
那么function[x]
将具有ReturnType
types。 再次查找operator[]
重载的ReturnType
。 如果有这样的方法,那么可以使用expression式function[x][y]
。
注意,与function(x, y)
, function[x][y]
是2个独立的调用。 编译器和运行时都不保证primefaces性。 另一个类似的例子是,libc说printf
是primefaces的,而在输出stream中连续调用重载的operator<<
则不是。 像一个声明
std::cout << "hello" << std::endl;
可能在multithreading应用程序中有问题,但类似
printf("%s%s", "hello", "\n");
好的。
总而言之,尽pipeC ++能够为您提供这样的语法糖,但并不是推荐的编程方式。
#include<iostream> using namespace std; class Array { private: int *p; public: int length; Array(int size = 0): length(size) { p=new int(length); } int& operator [](const int k) { return p[k]; } }; class Matrix { private: Array *p; public: int r,c; Matrix(int i=0, int j=0):r(i), c(j) { p= new Array[r]; } Array& operator [](const int& i) { return p[i]; } }; /*Driver program*/ int main() { Matrix M1(3,3); /*for checking purpose*/ M1[2][2]=5; }
struct test { using array_reference = int(&)[32][32]; array_reference operator [] (std::size_t index) { return m_data[index]; } private: int m_data[32][32][32]; };
find我自己的简单解决scheme。
可以使用专门的模板处理程序来重载多个[]。 只是为了说明它是如何工作的:
#include <iostream> #include <algorithm> #include <numeric> #include <tuple> #include <array> using namespace std; // the number '3' is the number of [] to overload (fixed at compile time) struct TestClass : public SubscriptHandler<TestClass,int,int,3> { // the arguments will be packed in reverse order into a std::array of size 3 // and the last [] will forward them to callSubscript() int callSubscript(array<int,3>& v) { return accumulate(v.begin(),v.end(),0); } }; int main() { TestClass a; cout<<a[3][2][9]; // prints 14 (3+2+9) return 0; }
现在定义SubscriptHandler<ClassType,ArgType,RetType,N>
来使前面的代码工作。 它只是表明如何做到这一点。 这个解决scheme是最佳的也没有错误(例如不是线程安全)。
#include <iostream> #include <algorithm> #include <numeric> #include <tuple> #include <array> using namespace std; template <typename ClassType,typename ArgType,typename RetType, int N> class SubscriptHandler; template<typename ClassType,typename ArgType,typename RetType, int N,int Recursion> class SubscriptHandler_ { ClassType*obj; array<ArgType,N+1> *arr; typedef SubscriptHandler_<ClassType,ArgType,RetType,N,Recursion-1> Subtype; friend class SubscriptHandler_<ClassType,ArgType,RetType,N,Recursion+1>; friend class SubscriptHandler<ClassType,ArgType,RetType,N+1>; public: Subtype operator[](const ArgType& arg){ Subtype s; s.obj = obj; s.arr = arr; arr->at(Recursion)=arg; return s; } }; template<typename ClassType,typename ArgType,typename RetType,int N> class SubscriptHandler_<ClassType,ArgType,RetType,N,0> { ClassType*obj; array<ArgType,N+1> *arr; friend class SubscriptHandler_<ClassType,ArgType,RetType,N,1>; friend class SubscriptHandler<ClassType,ArgType,RetType,N+1>; public: RetType operator[](const ArgType& arg){ arr->at(0) = arg; return obj->callSubscript(*arr); } }; template<typename ClassType,typename ArgType,typename RetType, int N> class SubscriptHandler{ array<ArgType,N> arr; ClassType*ptr; typedef SubscriptHandler_<ClassType,ArgType,RetType,N-1,N-2> Subtype; protected: SubscriptHandler() { ptr=(ClassType*)this; } public: Subtype operator[](const ArgType& arg){ Subtype s; s.arr=&arr; s.obj=ptr; s.arr->at(N-1)=arg; return s; } }; template<typename ClassType,typename ArgType,typename RetType> struct SubscriptHandler<ClassType,ArgType,RetType,1>{ RetType operator[](const ArgType&arg) { array<ArgType,1> arr; arr.at(0)=arg; return ((ClassType*)this)->callSubscript(arr); } };
template<class F> struct indexer_t{ F f; template<class I> std::result_of_t<F const&(I)> operator[](I&&i)const{ return f(std::forward<I>(i))1; } }; template<class F> indexer_t<std::decay_t<F>> as_indexer(F&& f){return {std::forward<F>(f)};}
这可以让你拿一个lambda,并产生一个索引器(支持[]
。
假设你有一个operator()
,它支持在onxe上传递两个坐标作为两个参数。 现在写[][]
支持只是:
auto operator[](size_t i){ return as_indexer( [i,this](size_t j)->decltype(auto) {return (*this)(i,j);} ); } auto operator[](size_t i)const{ return as_indexer( [i,this](size_t j)->decltype(auto) {return (*this)(i,j);} ); }
并做了。 没有自定义类的要求。
使用std::vector<std::vector<type*>>
,可以使用自定义input运算符构build内部向量,该运算符遍历数据并返回指向每个数据的指针。
例如:
size_t w, h; int* myData = retrieveData(&w, &h); std::vector<std::vector<int*> > data; data.reserve(w); template<typename T> struct myIterator : public std::iterator<std::input_iterator_tag, T*> { myIterator(T* data) : _data(data) {} T* _data; bool operator==(const myIterator& rhs){return rhs.data == data;} bool operator!=(const myIterator& rhs){return rhs.data != data;} T* operator*(){return data;} T* operator->(){return data;} myIterator& operator++(){data = &data[1]; return *this; } }; for (size_t i = 0; i < w; ++i) { data.push_back(std::vector<int*>(myIterator<int>(&myData[i * h]), myIterator<int>(&myData[(i + 1) * h]))); }
现场示例
这个解决scheme的优点是为您提供了一个真正的STL容器,所以您可以使用特殊的for循环,STLalgorithm等等。
for (size_t i = 0; i < w; ++i) for (size_t j = 0; j < h; ++j) std::cout << *data[i][j] << std::endl;
但是,它确实会创build指针向量,所以如果您使用的是这样的小型数据结构,则可以直接复制数组内的内容。
示例代码:
template<class T> class Array2D { public: Array2D(int a, int b) { num1 = (T**)new int [a*sizeof(int*)]; for(int i = 0; i < a; i++) num1[i] = new int [b*sizeof(int)]; for (int i = 0; i < a; i++) { for (int j = 0; j < b; j++) { num1[i][j] = i*j; } } } class Array1D { public: Array1D(int* a):temp(a) {} T& operator[](int a) { return temp[a]; } T* temp; }; T** num1; Array1D operator[] (int a) { return Array1D(num1[a]); } }; int _tmain(int argc, _TCHAR* argv[]) { Array2D<int> arr(20, 30); std::cout << arr[2][3]; getchar(); return 0; }
只有当你有可变长度的行,并且如果你需要矩形数组的时候,在内存使用/分配方面的效率太低,你才需要vector <vector>或T **。 看at()方法:
template<typename T > class array2d { protected: std::vector< T > _dataStore; size_t _sx; public: array2d(size_t sx, size_t sy = 1): _sx(sx), _dataStore(sx*sy) {} T& at( size_t x, size_t y ) { return _dataStore[ x+y*sx]; } const T& at( size_t x, size_t y ) const { return _dataStore[ x+y*sx]; } const T& get( size_t x, size_t y ) const { return at(x,y); } void set( size_t x, size_t y, const T& newValue ) { at(x,y) = newValue; } };
使用C ++ 11和标准库,你可以在一行代码中创build一个非常漂亮的二维数组:
std::array<std::array<int, columnCount>, rowCount> myMatrix {0}; std::array<std::array<std::string, columnCount>, rowCount> myStringMatrix; std::array<std::array<Widget, columnCount>, rowCount> myWidgetMatrix;
通过确定内部matrix表示行,可以使用myMatrix[y][x]
语法访问matrix:
myMatrix[0][0] = 1; myMatrix[0][3] = 2; myMatrix[3][4] = 3; std::cout << myMatrix[3][4]; // outputs 3 myStringMatrix[2][4] = "foo"; myWidgetMatrix[1][5].doTheStuff();
你可以使用ranged-for输出:
for (const auto &row : myMatrix) { for (const auto &elem : row) { std::cout << elem << " "; } std::cout << std::endl; }
(决定内部array
表示列将允许foo[x][y]
语法,但是您需要使用clumsier for(;;)
循环来显示输出。