Здесь вы пытаетесь использовать наследование для повторного использования кода, что, на мой взгляд, не является хорошим подходом к дизайну;наследование - для свободы реализации, а композиция - для повторного использования кода.
В этом случае, если бы действительно было необходимо поддерживать эти разные случаи, я бы формализовал 2d-массив:
template<typename T> class Array2D {
public:
virtual const T* operator[](int row_index) const = 0;
virtual T* operator[](int row_index) = 0;
virtual size_t rows() const = 0;
virtual size_t cols() const = 0;
};
Затем я бы предоставил реализации Array2D, которые вы указали:
template<typename T, int R, int C> class FixedArray2D : public Array2D {
public:
virtual const T* operator[](int row_index) const {
return &data_[row_index][0];
}
virtual T* operator[](int row_index) {
return &data_[row_index][0];
}
virtual size_t rows() const { return R; }
virtual size_t cols() const { return C; }
private:
T data_[R][C];
};
template<typename T> class DynamicArray2D : public Array2D {
public:
DynamicAray2D(int rows, int cols) {
// ...
}
// ...
};
На этом этапе вы можете создать экземпляр Array2D
, используя любой формат.Теперь любой код, который вы используете, может просто взять const Array2D&
или Array2D&
, где бы он ни имел дело с таким объектом.
Тем не менее, я думаю, что это, вероятно, ненужная сложность в том, что массив динамического размерабудет работать в любом случае, поэтому я просто согласился бы с этим, если не было веской причины поддерживать оба типа.