patterncppMinor
Basic Matrix Class in C++
Viewed 0 times
matrixclassbasic
Problem
I've made a simple Matrix class to learn C++. It doesn't use Templates so it only works with
I used these two blog posts as reference:
Description
One question I have is when I access a member of an instance, what is the difference between using
Also, when an instance is passed by reference, I can access its members even the private ones. You can see this behavior on the implementation of the copy constructor and at many other places. Is it good practice? Or should I have a public getter for accessing the private member of a class, even when they are the same type?
CMatrix.hpp
```
#ifndef CMatrix_hpp
#define CMatrix_hpp
#include
#include
class CMatrix {
private:
int* m_ptValues;
int m_totalSize;
int m_rows;
int m_columns;
public:
CMatrix(int rows, int columns); // base ctor.
CMatrix(const CMatrix& rhs); // copy ctor.
CMatrix& operator=(const CMatrix& rhs); // assign. ctor.
~CMatrix(); // dtor.
int& operator()(int row, int column);
int& operator()(int row, int column) const;
CMatrix& operator+=(int scalar);
CMatrix operator+(int scalar);
CMatrix& operator-=(int scalar);
CMatrix operator-(int scalar);
CMatrix& operator*=(int scalar);
CMatrix operator*(int scalar);
CMatrix& operator*=(const CMatrix& rhs);
CMatrix operator*(const CMatrix& rhs);
CMatrix& operator+=(const CMatrix& rhs);
CMatrix operator+(const CMatrix& rhs);
void reshape(int
int. I made it this way to really understand how to work with objects and memory. I'll probably move to the next level once I get feedback on this one.I used these two blog posts as reference:
- C++ Matrix Class
- C++ Tensor Class
Description
- The numbers (
int) are stored in a 1D array of fixed size. We can reshape the matrix but the new shape can't modify the total size
- It supports basic matrix and scalar operations (+,-,*)
- Some helpers functions are available like filling the matrix with one value, a range or random integers
One question I have is when I access a member of an instance, what is the difference between using
this->m_member or just m_member (if there is one)?Also, when an instance is passed by reference, I can access its members even the private ones. You can see this behavior on the implementation of the copy constructor and at many other places. Is it good practice? Or should I have a public getter for accessing the private member of a class, even when they are the same type?
CMatrix.hpp
```
#ifndef CMatrix_hpp
#define CMatrix_hpp
#include
#include
class CMatrix {
private:
int* m_ptValues;
int m_totalSize;
int m_rows;
int m_columns;
public:
CMatrix(int rows, int columns); // base ctor.
CMatrix(const CMatrix& rhs); // copy ctor.
CMatrix& operator=(const CMatrix& rhs); // assign. ctor.
~CMatrix(); // dtor.
int& operator()(int row, int column);
int& operator()(int row, int column) const;
CMatrix& operator+=(int scalar);
CMatrix operator+(int scalar);
CMatrix& operator-=(int scalar);
CMatrix operator-(int scalar);
CMatrix& operator*=(int scalar);
CMatrix operator*(int scalar);
CMatrix& operator*=(const CMatrix& rhs);
CMatrix operator*(const CMatrix& rhs);
CMatrix& operator+=(const CMatrix& rhs);
CMatrix operator+(const CMatrix& rhs);
void reshape(int
Solution
Looking at your header first:
Your interface doesn't use any of the names defined in these headers, so no need to include them here. (You may find you need them in the implementation, but they are not required for the header).
The first of those looks good, but there's a mistake in your second one. If the object is const, then you shouldn't allow the calling code to change its elements by returning modifiable references to them. Either of the following is consistent:
Next, these methods:
I'm not sure any of these methods belong in the public interface. If you provide suitable iterator types, you may be able to outsource some or all of these to standard algorithm functions.
Moving on to the implementation file, I'm a little concerned that you're doing your own memory allocation and deallocation. You could use a
This gives you a more convenient form of your loops:
Range checking:
If you're going to do range checking, you should also check that
#include
#include Your interface doesn't use any of the names defined in these headers, so no need to include them here. (You may find you need them in the implementation, but they are not required for the header).
int& operator()(int row, int column);
int& operator()(int row, int column) const;The first of those looks good, but there's a mistake in your second one. If the object is const, then you shouldn't allow the calling code to change its elements by returning modifiable references to them. Either of the following is consistent:
const int& operator()(int row, int column) const;
int operator()(int row, int column) const;Next, these methods:
void reshape(int newRows, int newColumns);
void show(); //used for dev. only
void range(int start, int defaultStep=1);
void fill(int value);
void randint(int lowerBound, int upperBound);I'm not sure any of these methods belong in the public interface. If you provide suitable iterator types, you may be able to outsource some or all of these to standard algorithm functions.
Moving on to the implementation file, I'm a little concerned that you're doing your own memory allocation and deallocation. You could use a
std::vector for your values, and you'd get your memory management and copy constructor for free. I'd suggest members likeclass CMatrix {
private:
std::vector values;
// size is found by values.size()
int rows;
// columns is values.size()/rows
}This gives you a more convenient form of your loops:
for (auto& i: values)
...;Range checking:
int& CMatrix::operator()(int row, int column) {
if (row >= m_rows || column >= m_columns) {
throw std::out_of_range("Index out of bounds");
}If you're going to do range checking, you should also check that
0 m_member unless you declare a local of the same name.- You can (and should, where necessary) access the private members of all objects of the same type - the access modifiers are a property of the code, not the particular instance you're manipulating.
Code Snippets
#include <iostream>
#include <random>int& operator()(int row, int column);
int& operator()(int row, int column) const;const int& operator()(int row, int column) const;
int operator()(int row, int column) const;void reshape(int newRows, int newColumns);
void show(); //used for dev. only
void range(int start, int defaultStep=1);
void fill(int value);
void randint(int lowerBound, int upperBound);class CMatrix {
private:
std::vector<int> values;
// size is found by values.size()
int rows;
// columns is values.size()/rows
}Context
StackExchange Code Review Q#155811, answer score: 6
Revisions (0)
No revisions yet.