想通过使用带变量的构造函数来声明数组
want to declare arrays by using constructor with variables
class matrix
{
public:
matrix();
matrix(int row, int column);
~matrix();
private:
const int DEFAULT_SIZE;
int size_row, size_column;
double *entry;
};
// main function
int
main()
{
//make a matrix of default size
matrix A; /* no error */
delete A;
//make 5 matrices of default size
matrix *B = new matrix [5]; /* no error */
delete [] B;
//make a matrix of size 15x15
matrix C(15, 15); /* no error */
delete C;
//make 5 matrices of size 15x15
matrix *D = new matrix(15, 15) [5]; /* compile error !! */
return 0;
}
//Define functions
matrix::matrix() : DEFAULT_SIZE(10)
{
size_row = DEFAULT_SIZE;
size_column = DEFAULT_SIZE;
entry = new double [size_row*size_column];
}
matrix::matrix(int row, int column) : DEFAULT_SIZE(10)
{
size_row = row;
size_column = column;
entry = new double [size_row*size_column];
}
matrix::~matrix()
{
delete [] entry;
}
我正在研究构造函数。
我想通过使用带变量的构造函数来声明数组。
你能更正我的代码行吗?
请参阅下面的行“//制作 5 个大小为 15x15 的矩阵”
另外,在这种情况下,如何使用析构函数?
要创建一个由 5 个元素组成的数组,每个元素都用 (15,15) 构造,您可以在 C++11 中执行以下操作:
matrix* D = new matrix[5]{
{15,15}, {15,15}, {15,15}, {15,15}, {15,15}
};
但是只使用 vector
:
会简单得多
std::vector<matrix> D(5, {15,15}); // C++11
std::vector<matrix> D(5, matrix(15,15)); // pre-C++11
看了你的源码,我看到的就是这个!在您的私人成员的 class 中,您的行和列大小不应该是 int 类型,它们应该是 unsigned int。它们应该是 unsigned int 的原因是因为没有 unsigned 的 int 默认是有符号值,这意味着它可以有负数。对于没有意义的矩阵中的行数和列数。对于 unsigned int 值,它的范围是 unsigned int 的 [0, max_value]。另一件需要注意的事情是,如果有人为行或列大小或两者输入 0 怎么办?那么你仍然没有有效的矩阵。这里需要做一点逻辑;如果有人为其中任何一个输入 0,那么您必须决定默认行为应该是什么。是否要使用默认值 10? 1x1 的值也没有意义!现在你可以有 1x4 或 4x1,那么它们将不完全是一个矩阵,但它们将是按顺序排列为行或列主要的向量。在我看来,没有任何参数的基本构造函数的默认矩阵大小应该是 2x2。如果用户为任一参数指定 1,则另一个参数应大于 1。这里也不需要 2 个构造函数,这是重复代码,只需 1 个构造函数即可完成。也不需要调用你的析构函数,当 class object 超出范围时会自动调用它。
对于矩阵,您认为元素应该是 public 以便于访问吗?
现在你的(元素)数组是私有的,这意味着没有外部 class 可以访问它们,现在如果这是你想要的行为那么你将需要函数来访问它们并在值需要更改时设置它们.
根据您的 class 实施,我在这里向您展示了我上面提到的更改。
#include <vector>
#include <array>
class Matrix {
private:
const unsigned int DEFAULT_SIZE;
unsigned int size_row, size_column;
double* elements;
public:
explicit Matrix( unsigned int row = 0; unsigned int column = 0 );
~Matrix();
// Copy Constructor
Matrix( const Matrix& c );
// Operator = Needed
Matrix& operator=( const Matrix& c );
}; // Matrix
Matrix::Matrix( unsigned int row, unsigned int column ) : DEFAULT_SIZE(2) {
// Check if both are 0 Or both are 1 - use default sizes
if ( (row == 0 && column == 0) ||
(row == 1 && column == 1) ) {
row = DEFAULT_SIZE;
column = DEFAULT_SIZE;
}
// Check [Row,Column] For [0,1] && [1,0]
if ( row == 0 && column == 1 ) {
row = 1;
column = DEFAULT_SIZE;
} else if ( row == 1 && column == 0 ) {
row = DEFAULT_SIZE;
column = 1;
}
size_row = row;
size_column = column;
element = new double[size_row * size_column];
} // Matrix
Matrix::~Matrix() {
delete [] elements
} // ~Matrix
Matrix::Matrix( const Matrix& c ) : DEFAULT(2) {
this->size_row = c.size_row;
this->size_column = c.size_column;
this->element = c.element;
} // Matrix(copy)
Matrix& Matrix::operator=( const Matrix& c ) {
// Assignment Can Only Happen If Both Matrices Are Of The Same Dimensions:
// You can not set a 4x3 = 6x9 for this does not make sense
if ( (this->size_row == c.size_row) &&
(this->size_column == c.size_column) ) {
this->element = c.element;
return *this;
} // operator=
至于你的主函数中的代码,我看到了一些需要修复的错误。前两行:
Matrix A;
delete A;
您正在声明矩阵 A;然后在下一行你调用 A 上的 delete。
这是您的第一个错误:A 是 Matrix 的一个实例。这是属于主函数范围的局部堆栈变量。无需为此调用删除!当您的 Matrix (A) 实例超出范围时,会在幕后为您隐式调用 Matrix::~Matrix(),无需调用它。
你接下来的两行代码:
Matrix* B = new Matrix[5];
delete [] B;
这两个是正确的,这里没有问题。您的实例 B 是指向类型 object Matrix 的指针,因为这里使用了 new 它是在堆上创建的,并且因为您有 [5] B 不仅是指向此类型的指针,而且是堆上的指针到你动态分配的数组的第一个地址。然后你用 B 上的 [] 运算符调用 delete,这是正确的。
你接下来的两行代码:
Matrix C(15,15);
delete C;
您正在声明一个名为 C 的矩阵实例 object 在您现在使用定义的构造函数的堆栈上。同样在第二行,不需要在 C 上调用 delete。
至于你的最后两行代码,这并不像你想做的那么简单,但也不是那么微不足道。为了创建默认大小均为 15x15 的动态矩阵数组,需要做更多的工作。为了正确执行此操作,您可以从 class 实现中看到我添加了一个复制构造函数和一个重载的 = 运算符。实现这一点需要三个步骤。
// First Step - Create A Single Stack Instance With Size [15,15]
Matrix D = Matrix( 15, 15 ); // This Will Be Used Later To Populate Your Array
// Second Step - Create An Array of 5 Matrices On The Heap
Matrix* E = new Matrix[5]; // Right Now All Five Are Using Default Size 2x2.
// Step Three Now We Update Them Using Our operator=()
for ( unsigned int i = 0; i < 5; i++ ) {
E[i] = D;
}
// Then Delete the Array
delete [] E; // Only Need To Delete E
然而这将不起作用:由于我们的 operator=() 是如何定义的!那么我们如何实现呢?有两种方法,两种方法都有效。 So You Can Remove Matrix E、for 循环和 delete [] E 行。留下 Matrix D 因为需要它!
第一个更简单:如果您注意到我在这种情况下包含了来自 STL 的向量和数组,我将使用向量 class,因为它是最常用的。
// We already have: Matrix D = Matrix( 15, 15 );
// You Want an Array of 5
std::vector<Matrix> vMatrices; // This will create a vector of stack Matrices but at first it will be "EMPTY"
for ( unsigned int i = 0; i < 5; i++ ) {
vMatrices.push_back( D );
}
// Now You Have A vector of 5 Matrices.
// If You Want Vector of Pointers
std::vector<Matrix*> vpMatrices;
for ( unsigned int i = 0; i < 5; i++ ) {
vpMatrices.push_back( &D );
}
// To clean up your vectors you can simply do
vMatrices.clear();
vpMatrices.clear();
// The Other Way Would Be To Use std::array but it is less commonly used.
// If You know you will only ever need a set amount this works good
std::array<Matrix, 5> aMatrices;
for ( unsigned int i = 0; i < 5; i++ ) {
aMatrices.at(i) = D;
}
// For Holding Pointers
std::array<Matrix*, 5> apMatrices;
for ( unsigned int i = 0; i < 5; i++ ) {
apMatrices.at(i) = &D;
}
// To Clean Up std::array To Be Honest Not really sure for I do not use them
// But using it here just as an illustration that there are plenty of predefined containers
// to use to hold multiple elements of the same data type.
作为关于您的 class 的最后说明,您正在创建矩阵的大小并根据大小定义元素数组,但是由于一切都是私有的,您无法填充它或访问它。将其保密意味着您必须实现函数来执行此操作,并考虑矩阵的性质,以便它们成为 "Store" 数据或 "Function Calls" 或作为计算和运算的数学 Object。您不希望附加功能的开销,因为这会影响性能。将行和列的大小保持私有并没有错,因为一旦它们被定义,就不需要在 class 之外访问它们。但是代表 MxN 矩阵的一维数组应该 publicly 定义。您还应该定义 operator[] 。
如果您想了解基本数学库如何实现矩阵,请查看为与 OpenGL 着色器 lang 一起编写的 GLM 数学库年龄 GLSL。
这个图书馆是 Headers 唯一的图书馆。无需 link 或包含 *.dlls 或 *.libs。您需要做的就是将它存储到您计算机上的一个文件夹中,并为您的系统设置一个指向其主文件夹的环境变量。然后在 IDE 如果您使用的是 VS,那么您在项目属性的附加包含部分中所要做的就是使用定义的环境变量。这是为了使用它!但如果只是查看其内容,您可以将其下载到任何文件夹并打开任何 *.h 文件。然后你可以看到他们是如何实现 Matrix classes 的!您会注意到它们是模板类型,并且具有预定义的矩阵类型,例如 mat2x2、mat2x3、mat2x4、mat3x2、mat3x3、mat3x4、mat4x2、mat4x3 和 mat4x4。这符合编写专注于 2D 和 3D 图形的程序和着色器的性质,因此所需的最小尺寸是 2x2,真正需要的最大尺寸是 4x4。它们还定义了不同大小的向量 classes,并且您的矩阵可以由不同大小的向量构建。但这应该作为一个指导方针。这是他们的 link
GLM
class matrix
{
public:
matrix();
matrix(int row, int column);
~matrix();
private:
const int DEFAULT_SIZE;
int size_row, size_column;
double *entry;
};
// main function
int
main()
{
//make a matrix of default size
matrix A; /* no error */
delete A;
//make 5 matrices of default size
matrix *B = new matrix [5]; /* no error */
delete [] B;
//make a matrix of size 15x15
matrix C(15, 15); /* no error */
delete C;
//make 5 matrices of size 15x15
matrix *D = new matrix(15, 15) [5]; /* compile error !! */
return 0;
}
//Define functions
matrix::matrix() : DEFAULT_SIZE(10)
{
size_row = DEFAULT_SIZE;
size_column = DEFAULT_SIZE;
entry = new double [size_row*size_column];
}
matrix::matrix(int row, int column) : DEFAULT_SIZE(10)
{
size_row = row;
size_column = column;
entry = new double [size_row*size_column];
}
matrix::~matrix()
{
delete [] entry;
}
我正在研究构造函数。 我想通过使用带变量的构造函数来声明数组。 你能更正我的代码行吗?
请参阅下面的行“//制作 5 个大小为 15x15 的矩阵”
另外,在这种情况下,如何使用析构函数?
要创建一个由 5 个元素组成的数组,每个元素都用 (15,15) 构造,您可以在 C++11 中执行以下操作:
matrix* D = new matrix[5]{
{15,15}, {15,15}, {15,15}, {15,15}, {15,15}
};
但是只使用 vector
:
std::vector<matrix> D(5, {15,15}); // C++11
std::vector<matrix> D(5, matrix(15,15)); // pre-C++11
看了你的源码,我看到的就是这个!在您的私人成员的 class 中,您的行和列大小不应该是 int 类型,它们应该是 unsigned int。它们应该是 unsigned int 的原因是因为没有 unsigned 的 int 默认是有符号值,这意味着它可以有负数。对于没有意义的矩阵中的行数和列数。对于 unsigned int 值,它的范围是 unsigned int 的 [0, max_value]。另一件需要注意的事情是,如果有人为行或列大小或两者输入 0 怎么办?那么你仍然没有有效的矩阵。这里需要做一点逻辑;如果有人为其中任何一个输入 0,那么您必须决定默认行为应该是什么。是否要使用默认值 10? 1x1 的值也没有意义!现在你可以有 1x4 或 4x1,那么它们将不完全是一个矩阵,但它们将是按顺序排列为行或列主要的向量。在我看来,没有任何参数的基本构造函数的默认矩阵大小应该是 2x2。如果用户为任一参数指定 1,则另一个参数应大于 1。这里也不需要 2 个构造函数,这是重复代码,只需 1 个构造函数即可完成。也不需要调用你的析构函数,当 class object 超出范围时会自动调用它。
对于矩阵,您认为元素应该是 public 以便于访问吗? 现在你的(元素)数组是私有的,这意味着没有外部 class 可以访问它们,现在如果这是你想要的行为那么你将需要函数来访问它们并在值需要更改时设置它们.
根据您的 class 实施,我在这里向您展示了我上面提到的更改。
#include <vector>
#include <array>
class Matrix {
private:
const unsigned int DEFAULT_SIZE;
unsigned int size_row, size_column;
double* elements;
public:
explicit Matrix( unsigned int row = 0; unsigned int column = 0 );
~Matrix();
// Copy Constructor
Matrix( const Matrix& c );
// Operator = Needed
Matrix& operator=( const Matrix& c );
}; // Matrix
Matrix::Matrix( unsigned int row, unsigned int column ) : DEFAULT_SIZE(2) {
// Check if both are 0 Or both are 1 - use default sizes
if ( (row == 0 && column == 0) ||
(row == 1 && column == 1) ) {
row = DEFAULT_SIZE;
column = DEFAULT_SIZE;
}
// Check [Row,Column] For [0,1] && [1,0]
if ( row == 0 && column == 1 ) {
row = 1;
column = DEFAULT_SIZE;
} else if ( row == 1 && column == 0 ) {
row = DEFAULT_SIZE;
column = 1;
}
size_row = row;
size_column = column;
element = new double[size_row * size_column];
} // Matrix
Matrix::~Matrix() {
delete [] elements
} // ~Matrix
Matrix::Matrix( const Matrix& c ) : DEFAULT(2) {
this->size_row = c.size_row;
this->size_column = c.size_column;
this->element = c.element;
} // Matrix(copy)
Matrix& Matrix::operator=( const Matrix& c ) {
// Assignment Can Only Happen If Both Matrices Are Of The Same Dimensions:
// You can not set a 4x3 = 6x9 for this does not make sense
if ( (this->size_row == c.size_row) &&
(this->size_column == c.size_column) ) {
this->element = c.element;
return *this;
} // operator=
至于你的主函数中的代码,我看到了一些需要修复的错误。前两行:
Matrix A;
delete A;
您正在声明矩阵 A;然后在下一行你调用 A 上的 delete。 这是您的第一个错误:A 是 Matrix 的一个实例。这是属于主函数范围的局部堆栈变量。无需为此调用删除!当您的 Matrix (A) 实例超出范围时,会在幕后为您隐式调用 Matrix::~Matrix(),无需调用它。
你接下来的两行代码:
Matrix* B = new Matrix[5];
delete [] B;
这两个是正确的,这里没有问题。您的实例 B 是指向类型 object Matrix 的指针,因为这里使用了 new 它是在堆上创建的,并且因为您有 [5] B 不仅是指向此类型的指针,而且是堆上的指针到你动态分配的数组的第一个地址。然后你用 B 上的 [] 运算符调用 delete,这是正确的。
你接下来的两行代码:
Matrix C(15,15);
delete C;
您正在声明一个名为 C 的矩阵实例 object 在您现在使用定义的构造函数的堆栈上。同样在第二行,不需要在 C 上调用 delete。
至于你的最后两行代码,这并不像你想做的那么简单,但也不是那么微不足道。为了创建默认大小均为 15x15 的动态矩阵数组,需要做更多的工作。为了正确执行此操作,您可以从 class 实现中看到我添加了一个复制构造函数和一个重载的 = 运算符。实现这一点需要三个步骤。
// First Step - Create A Single Stack Instance With Size [15,15]
Matrix D = Matrix( 15, 15 ); // This Will Be Used Later To Populate Your Array
// Second Step - Create An Array of 5 Matrices On The Heap
Matrix* E = new Matrix[5]; // Right Now All Five Are Using Default Size 2x2.
// Step Three Now We Update Them Using Our operator=()
for ( unsigned int i = 0; i < 5; i++ ) {
E[i] = D;
}
// Then Delete the Array
delete [] E; // Only Need To Delete E
然而这将不起作用:由于我们的 operator=() 是如何定义的!那么我们如何实现呢?有两种方法,两种方法都有效。 So You Can Remove Matrix E、for 循环和 delete [] E 行。留下 Matrix D 因为需要它!
第一个更简单:如果您注意到我在这种情况下包含了来自 STL 的向量和数组,我将使用向量 class,因为它是最常用的。
// We already have: Matrix D = Matrix( 15, 15 );
// You Want an Array of 5
std::vector<Matrix> vMatrices; // This will create a vector of stack Matrices but at first it will be "EMPTY"
for ( unsigned int i = 0; i < 5; i++ ) {
vMatrices.push_back( D );
}
// Now You Have A vector of 5 Matrices.
// If You Want Vector of Pointers
std::vector<Matrix*> vpMatrices;
for ( unsigned int i = 0; i < 5; i++ ) {
vpMatrices.push_back( &D );
}
// To clean up your vectors you can simply do
vMatrices.clear();
vpMatrices.clear();
// The Other Way Would Be To Use std::array but it is less commonly used.
// If You know you will only ever need a set amount this works good
std::array<Matrix, 5> aMatrices;
for ( unsigned int i = 0; i < 5; i++ ) {
aMatrices.at(i) = D;
}
// For Holding Pointers
std::array<Matrix*, 5> apMatrices;
for ( unsigned int i = 0; i < 5; i++ ) {
apMatrices.at(i) = &D;
}
// To Clean Up std::array To Be Honest Not really sure for I do not use them
// But using it here just as an illustration that there are plenty of predefined containers
// to use to hold multiple elements of the same data type.
作为关于您的 class 的最后说明,您正在创建矩阵的大小并根据大小定义元素数组,但是由于一切都是私有的,您无法填充它或访问它。将其保密意味着您必须实现函数来执行此操作,并考虑矩阵的性质,以便它们成为 "Store" 数据或 "Function Calls" 或作为计算和运算的数学 Object。您不希望附加功能的开销,因为这会影响性能。将行和列的大小保持私有并没有错,因为一旦它们被定义,就不需要在 class 之外访问它们。但是代表 MxN 矩阵的一维数组应该 publicly 定义。您还应该定义 operator[] 。
如果您想了解基本数学库如何实现矩阵,请查看为与 OpenGL 着色器 lang 一起编写的 GLM 数学库年龄 GLSL。 这个图书馆是 Headers 唯一的图书馆。无需 link 或包含 *.dlls 或 *.libs。您需要做的就是将它存储到您计算机上的一个文件夹中,并为您的系统设置一个指向其主文件夹的环境变量。然后在 IDE 如果您使用的是 VS,那么您在项目属性的附加包含部分中所要做的就是使用定义的环境变量。这是为了使用它!但如果只是查看其内容,您可以将其下载到任何文件夹并打开任何 *.h 文件。然后你可以看到他们是如何实现 Matrix classes 的!您会注意到它们是模板类型,并且具有预定义的矩阵类型,例如 mat2x2、mat2x3、mat2x4、mat3x2、mat3x3、mat3x4、mat4x2、mat4x3 和 mat4x4。这符合编写专注于 2D 和 3D 图形的程序和着色器的性质,因此所需的最小尺寸是 2x2,真正需要的最大尺寸是 4x4。它们还定义了不同大小的向量 classes,并且您的矩阵可以由不同大小的向量构建。但这应该作为一个指导方针。这是他们的 link GLM