在C ++程序中,这里有两个操作符标题,用作未显示的矩阵实现的setter和getter。
double* Matrix::operator[](unsigned int row) const throw (MatrixException);
double* Matrix::operator[](unsigned int row) throw (MatrixException);
在不了解前述运算符的实现的情况下,仅通过查看如何定义上述运算符,如果这两种方法都被实现,那么矩阵程序中的设计缺陷将是什么。
关于[]运算符如何工作的说明: 矩阵设置如下:
Matrix *a = new Matrix(1,2); //matrix with one row and two columns
a[0][0] = 3.0;
a[0][1] = 2.3;
//to access a matrix value
double* b = a[0][1];
delete a;
编辑:您将在操作员定义中更改哪些内容以修复设计缺陷?
答案 0 :(得分:0)
第一个设计缺陷是使用异常规范,在 C ++ 11 中弃用。
第二个设计缺陷是您可以索引行列,并且类无法检查它。即,
Matrix a( 1, 2 );
double b = a[0][4];
通过使用代理可以进行边界检查。
struct Matrix {
struct Column {
double operator[](unsigned int column);
};
Column operator[](unsigned int row);
};
最后,你的例子完全是虚假的。您将a
声明为指针,因此当您下标a[0][0]
时,您实际上是先订阅指针,然后是行。
答案 1 :(得分:0)
有一些缺陷。
最明显的一个是手动内存管理不必要地使用动态内存。每当你看到delete
时,你几乎都知道出了什么问题,而且只要你看到new
,就应该怀疑。
Matrix a(1, 2); // no new needed
a[0][0] = 3.0;
a[0][1] = 2.3;
double * b = a[0][1];
// no delete needed
这可以完全防止内存泄漏。它还避免了你没有实际索引数组的错误(你需要使用(*a)[0][0]
来获取第一个元素)。
其次,您应该返回对值的引用,而不是指针。
第三,你应该是一个函数,它返回值并将两个索引作为参数,而不是重载operator[]
以返回一个你必须再次取消引用的数组。 http://www.parashift.com/c++-faq/matrix-subscript-op.html
这允许您检查边界,假设Matrix
知道它自己的大小是什么(它必须存储两个整数数据成员)。
double const & Matrix::at(size_t const row, size_t const column) const {
check_bounds(row, column);
return implementation_detail();
}
明确实施double &
版本。按照目前的情况,您的const
成员函数版本会返回double *
,而不是通过返回const
来传递double const *
传递(尽管仍然首选引用)。
另一个潜在的缺陷是像Matrix
这样的泛型类可能应该在类型上进行参数化:
template<typename T>
class Matrix {
public:
typedef T value_type;
...
};
因此,您的示例实际上将使用Matrix<double>
作为类型。
最后,我会对异常规范说不。它们往往会导致比修复更多的错误,这就是为什么它们在C ++ 11中被弃用的原因。