008
16.07.2003, 17:28 Uhr
Tommix
|
Hallo, @virtual: Visual C meckert bei Deinem Code bei "array_type& data;" 'Verweis auf ein Feld der Groesse Null ist ungueltig"'. Ich bin mir aber gerade bei templates in Zusammenhang mit diesem Compiler nie so ganz sicher, wie falsch die Fehler sind.
Eigentlich wollte ich was anderes, sozusagen als Zusatzfrage (liegt schon ewig in der Schublade und war mir nie einen eigenen Thread wert). Ich wollte schon immer mal eine zweidimensionale Arrayklasse machen, mit der man wie mit einem "normalen" Feld arbeiten kann (var[x][y]), bei der aber die Indizes auf Gültigkeit geprüft werden. Nach dem Motto: Langsam aber sicher. Ich bin bis hierhin gekommen:
C++: |
#ifndef NULL #define NULL 0 #endif
class CMatrixException { public: enum TCause { NoError = 0, Memory, Bounds };
private: TCause m_cause;
public: CMatrixException(TCause cause) : m_cause(cause) {}
virtual ~CMatrixException() {}
};
template<class TYPE> class CMatrix { public: CMatrix(TYPE zero = static_cast<TYPE>(0)); CMatrix(int xSize, int ySize, TYPE zero = static_cast<TYPE>(0)); virtual ~CMatrix();
void SetSize(int xMax, int yMax, bool preserve = true); void SetAll(TYPE value); void Clear() {SetAll(null);} void SetAt(int x, int y, TYPE value); TYPE GetAt(int x, int y) const; TYPE* operator[] (int y) const;
private: void SetAll(TYPE* ptr, TYPE value, int elements); TYPE& At(int x, int y) const; TYPE* m_pElements;
int m_xMax; int m_yMax;
const TYPE null; };
#define Error(cause) throw new CMatrixException(cause)
// Interface
template <class TYPE> CMatrix<TYPE>::CMatrix(TYPE zero) : m_pElements(NULL), m_xMax(0), m_yMax(0), null(static_cast<TYPE>(zero)) { }
template <class TYPE> CMatrix<TYPE>::CMatrix(int xSize, int ySize, TYPE zero) : m_pElements(NULL), null(static_cast<TYPE>(zero)) { SetSize(xSize, ySize, false); }
template <class TYPE> CMatrix<TYPE>::~CMatrix() { delete[] m_pElements; }
template <class TYPE> void CMatrix<TYPE>::SetSize(int xSize, int ySize, bool preserve) { if((xSize <= 0) || (ySize <= 0)) { Error(CMatrixException::Bounds); // negative bounds } else { TYPE* pData = new TYPE[xSize*ySize];
if (pData) { SetAll(pData, null, xSize*ySize); if (preserve) { int xMax = xSize < m_xMax ? xSize : m_xMax; int yMax = ySize < m_yMax ? ySize : m_yMax;
//.. Kopieren for (int y = 0; y < yMax; ++y) { TYPE* pSrc = m_pElements+(y*m_xMax); TYPE* pDst = pData+(y*xMax);
for (int x = 0; x < xMax; ++x) { *(pDst++) = *(pSrc++); } } }
m_xMax = xSize; m_yMax = ySize;
delete m_pElements; m_pElements = pData; } else { Error(CMatrixException::Memory); // new failed } } }
template <class TYPE> void CMatrix<TYPE>::SetAll(TYPE value) { SetAll(m_pElements, value, m_xMax*m_yMax); }
template <class TYPE> void CMatrix<TYPE>::SetAt(int x, int y, TYPE value) { At(x, y) = value; }
template <class TYPE> TYPE CMatrix<TYPE>::GetAt(int x, int y) const { return At(x, y); }
template <class TYPE> TYPE* CMatrix<TYPE>::operator [] (int y) const { return &At(0, y); }
template <class TYPE> void CMatrix<TYPE>::SetAll(TYPE* ptr, TYPE value, int elements) { for (int index = 0; index < elements; ++index) *(ptr++) = value; }
template <class TYPE> TYPE& CMatrix<TYPE>::At(int x, int y) const { if ((x < 0) || (x >= m_xMax) || (y < 0) || (y >= m_yMax)) Error(CMatrixException::Bounds); else return m_pElements[y*m_xMax+x]; }
#undef Error
class CDoubleMatrix : public CMatrix<double> { public: CDoubleMatrix(); CDoubleMatrix(int xSize, int ySize); virtual ~CDoubleMatrix();
};
CDoubleMatrix::CDoubleMatrix() : CMatrix<double>(0.0) { }
CDoubleMatrix::CDoubleMatrix(int xSize, int ySize) : CMatrix<double>(xSize, ySize, 0.0) { }
CDoubleMatrix::~CDoubleMatrix() { }
#include <iostream>
int main() { CDoubleMatrix matrix(10, 10); matrix.SetAt(3, 3, 1.234); matrix[3][4] = -2.345; std::cout << matrix.GetAt(3, 3) << std::endl; std::cout << matrix[3][4] << std::endl;
try { matrix[11][1]; // wird abgefangen matrix[1][11]; // wird nicht abgefangen } catch(CMatrixException* pException) { std::cerr << "Error" << std::endl; delete pException; }
return 0; }
|
(Durch das viele rumprobieren ist vermutlich etlicher Müll mit drin.) Wie man am Ende sieht, wird der erste Index geprüft und der zweite nicht.
Hat einer 'ne Idee? Falls das zu leicht ist: Wie kann man dieses Methodik auf beliebig viele Dimensionen erweitern?
Gruss, Tommix |