0

When multiplying a matrix by a vector, a square matrix is ​​returned, although it is built rectangular in the body of the overload. I checked the "=" operator and the copy constructor, am I missing something or is the problem something else? There is also an error when multiplying a square matrix by a rectangular one (column) because of what this problem can be? main:

#include <iostream>
#include "/home/qapfuc/Documents/Nizhny-Novgorod-State-University/Fourth LAB/vectorLib/MyMatrix.h"
#include "/home/qapfuc/Documents/Nizhny-Novgorod-State-University/Fourth LAB/vectorLib/MyVector.h"

int main(){
    MyVector<int> b{2,2};
    MyMatrix<int> y(2,2);
    MyMatrix<int> yy(2,2);
    std::cin>>yy;
    std::cin>>y;
    std::cout<<yy<<std::endl;
    yy=yy*y;
    std::cout<<yy<<std::endl;
}

MyMatrix.h

#pragma once
#include "MyVector.h"

template <class ClassName>
class MyMatrix :public MyVector<ClassName>{
protected:
        ClassName **ArrayMatrix;
        int ArraySize_x = 3;
        int ArraySize_y = 3;
public:
        //Конструкторы
        MyMatrix() {
            ArrayMatrix = new ClassName*[ArraySize_x];
            for (int i = 0; i < ArraySize_x; i++) {
                ArrayMatrix[i] = new ClassName[ArraySize_y];
            }
            for (int i = 0; i < ArraySize_x; i++){
                for (int j = 0; j < ArraySize_y; j++){
                    ArrayMatrix[i][j]=0;
                }
            }
        }
        MyMatrix(int x,int y){
            ArraySize_x=x;
            ArraySize_y=y;
            ArrayMatrix = new ClassName*[ArraySize_x];
            for (int i = 0; i < ArraySize_x; i++) {
                ArrayMatrix[i] = new ClassName[ArraySize_y];
            }
            for (int i = 0; i < ArraySize_x; i++){
                for (int j = 0; j < ArraySize_y; j++){
                    ArrayMatrix[i][j]=0;
                }
            }
        }
        MyMatrix(const MyMatrix<ClassName> &other){
            ArraySize_x=other.ArraySize_x;
            ArraySize_y=other.ArraySize_y;
            ArrayMatrix = new  ClassName*[ArraySize_x];
            for (int i = 0; i < ArraySize_x; i++) {
                ArrayMatrix[i] = new ClassName[ArraySize_y];
            }
            for (int i = 0; i < ArraySize_x; i++){
                for (int j = 0; j < ArraySize_y; j++){
                    ArrayMatrix[i][j]=other.ArrayMatrix[i][j];
                }
            }
        }
        ~MyMatrix(){
            for (int i = 0; i < ArraySize_x; i++) {
                delete [] ArrayMatrix[i];
            }
            delete [] ArrayMatrix;
        }

        //Операторы
        auto operator[](const int index){
            return ArrayMatrix[index];
        };
        MyMatrix operator = (MyMatrix<ClassName> other) {
            if ((ArraySize_x == other.ArraySize_x) && (ArraySize_y == other.ArraySize_y)) {
                for (int i = 0; i < ArraySize_x; i++) {
                    for (int j = 0; j < ArraySize_y; j++) {
                        ArrayMatrix[i][j] = other.ArrayMatrix[i][j];
                    }
                }
                return *this;
            } else{
                MyMatrix<ClassName> temp(other.ArraySize_x,other.ArraySize_y);
                for (int i = 0; i < other.ArraySize_x; i++) {
                    for (int j = 0; j < other.ArraySize_y; j++) {
                        temp.ArrayMatrix[i][j] = other.ArrayMatrix[i][j];
                    }
                }
                return temp;
            }
        };
        MyMatrix operator+(MyMatrix<ClassName>& other){
            if ((ArraySize_x == other.ArraySize_x) && (ArraySize_y == other.ArraySize_y)) {
                MyMatrix<ClassName> temp(ArraySize_x, ArraySize_y);
                for (int i = 0; i < ArraySize_x; i++) {
                    for (int j = 0; j < ArraySize_y; j++) {
                        temp.ArrayMatrix[i][j] = ArrayMatrix[i][j] + other.ArrayMatrix[i][j];
                    }
                }
                return temp;
            }else{
                std::cout<<"The number of rows does not match the number of columns in the matrices. Check the matrices."<<std::endl;
                abort();
            }
        };
        MyMatrix operator-(MyMatrix<ClassName>& other){
            if ((ArraySize_x == other.ArraySize_x) && (ArraySize_y == other.ArraySize_y)) {
                MyMatrix<ClassName> temp(ArraySize_x, ArraySize_y);
                for (int i = 0; i < ArraySize_x; i++) {
                    for (int j = 0; j < ArraySize_y; j++) {
                        temp.ArrayMatrix[i][j] = ArrayMatrix[i][j] - other.ArrayMatrix[i][j];
                    }
                }
                return temp;
            }else{
                std::cout<<"The number of rows does not match the number of columns in the matrices. Check the matrices."<<std::endl;
                abort();
            }
        };
        MyMatrix operator*(MyMatrix<ClassName>& other){
            if(ArraySize_y==other.ArraySize_x) {
                MyMatrix<ClassName> temp(ArraySize_x, other.ArraySize_y);
                for (int i = 0; i < ArraySize_x; i++) {
                    for (int j = 0; j < other.ArraySize_x; j++) {
                        for (int k = 0; k < ArraySize_y; k++) {
                            temp.ArrayMatrix[i][j] += ArrayMatrix[i][k] * other.ArrayMatrix[k][j];
                        }
                    }
                }
                return temp;
            }
            else{
                std::cout<<"The number of rows does not match the number of columns in the matrices. Check the matrices."<<std::endl;
                abort();
            }
        };





        MyMatrix operator*(MyVector<ClassName>& other){
            if(ArraySize_y==other.GetSize()) {
                MyMatrix<ClassName> temp(other.GetSize(),1);
                for (int i = 0; i < temp.ArraySize_x; i++) {
                    for (int j = 0; j < 1; j++) {
                        for (int k = 0; k < other.GetSize(); k++) {
                            temp.ArrayMatrix[i][j] += ArrayMatrix[i][k] * other.GetArrayVector(k);
                        }
                    }
                }
                std::cout<<temp<<std::endl;
                return temp;
            }
            else{
                std::cout<<"The number of rows does not match the number of columns in the matrices. Check the matrices."<<std::endl;
                abort();
            }
        };





        friend std::ostream& operator<< (std::ostream& os, MyMatrix<ClassName> &Input){
            for( int i=0; i<Input.ArraySize_x;i++){
                for( int j=0; j<Input.ArraySize_y;j++) {
                    os << Input.ArrayMatrix[i][j]<<" ";
                }
                os<<std::endl;
            }
            return os;
        };
        friend std::istream& operator>>(std::istream &in, MyMatrix<ClassName>& Output){
            for( int i=0; i<Output.ArraySize_x;i++){
                for( int j=0; j<Output.ArraySize_y;j++) {
                    in >> Output.ArrayMatrix[i][j];
                }
            }
            return in;
        };

};
template <class ClassName>
bool operator==(MyMatrix<ClassName> &First,MyMatrix<ClassName> &Second){
    if((First.ArraySize_x!=Second.ArraySize_x) || (First.ArraySize_y!=Second.ArraySize_y)){
        return false;
    }
    for( int i=0;i<First.ArraySize_x;i++){
        for( int j=0;j<First.ArraySize_y;j++) {
            if (First.ArrayMatrix[i][j] != Second.ArrayMatrix[i][j]) {
                return false;
            }
        }
    }
    return true;
}
template <class ClassName>
bool operator!=(MyMatrix<ClassName> &First,MyMatrix<ClassName> &Second){
    return not(First==Second);
}

MyVector.h

#pragma once
#include "MyMatrix.h"

template <class ClassName>
class MyVector{
protected:
        ClassName* ArrayVector;
        int ArraySize = 3;
public:
        ClassName GetArrayVector(int index){
            return ArrayVector[index];
        }
        int GetSize(){
            return ArraySize;
        }
        //Конструкторы
        MyVector(){
            ArrayVector = new ClassName[ArraySize];
            for( int i=0; i<ArraySize; i++){
                ArrayVector[i]=0;
            }
        }
        MyVector(int Size){
            ArraySize=Size;
            ArrayVector = new ClassName[ArraySize];
            for( int i=0; i<ArraySize; i++){
                ArrayVector[i]=0;
            }
        }
        MyVector(const std::initializer_list<ClassName> &list):MyVector(list.size()){
            int count = 0;
            for (auto &element : list)
            {
                ArrayVector[count] = element;
                ++count;
            }
        }
        MyVector(const MyVector<ClassName> &other){
            ArraySize=other.ArraySize;
            ArrayVector = new  ClassName[ArraySize];
            for( int i=0;i<ArraySize;i++){
                ArrayVector[i]=other.ArrayVector[i];
            }
        }
        ~MyVector(){
                delete [] ArrayVector;
        }

        //Операторы
        int& operator[](const int index){
            return ArrayVector[index];
        };
        MyVector operator=(MyVector<ClassName> other){
            if (ArraySize==other.ArraySize) {
                for (int i = 0; i < ArraySize; i++) {
                    ArrayVector[i] = other.ArrayVector[i];
                }
                return *this;
            } else {
                std::cout<<"The number of elements is not correct. Check the vector."<<std::endl;
                abort();
            }
        };
        MyVector operator+(MyVector<ClassName> other){
            if (ArraySize==other.ArraySize) {
                MyVector<ClassName> temp(ArraySize);
                for (int i = 0; i < ArraySize; i++) {
                    temp.ArrayVector[i] = ArrayVector[i] + other.ArrayVector[i];
                }
                return temp;
            }else{
                std::cout<<"The number of elements is not correct. Check the vector."<<std::endl;
                abort();
            }
        };
        MyVector operator-(MyVector<ClassName> other){
            if (ArraySize==other.ArraySize) {
                MyVector<ClassName> temp(ArraySize);
                for (int i = 0; i < ArraySize; i++) {
                    temp.ArrayVector[i] = ArrayVector[i] - other.ArrayVector[i];
                }
                return temp;
            } else {
                std::cout<<"The number of elements is not correct. Check the vector."<<std::endl;
                abort();
            }
        };
        MyVector operator*(MyVector<ClassName> other){
            if (ArraySize==other.ArraySize) {
                MyVector<ClassName> temp(ArraySize);
                for (int i = 0; i < ArraySize; i++) {
                    temp.ArrayVector[i] = ArrayVector[i] * other.ArrayVector[i];
                }
                return temp;
            } else {
                std::cout<<"The number of elements is not correct. Check the vector."<<std::endl;
                abort();
            }
        };
        MyVector operator/(MyVector<ClassName> other){
            if (ArraySize==other.ArraySize) {
                MyVector<ClassName> temp(ArraySize);
                for (int i = 0; i < ArraySize; i++) {
                    temp.ArrayVector[i] = (ArrayVector[i])/(other.ArrayVector[i]);
                }
                return temp;
            } else {
                std::cout<<"The number of elements is not correct. Check the vector."<<std::endl;
                abort();
            }
        };

        friend std::ostream& operator<< (std::ostream& os, MyVector<ClassName> &Input){
            for( int i=0; i<Input.ArraySize;i++){
                os<<Input.ArrayVector[i]<<std::endl;
            }
            return os;
        };

        friend std::istream& operator>>(std::istream &in, MyVector<ClassName>& Output){
            for( int i=0; i<Output.ArraySize;i++){
                in>>Output.ArrayVector[i];
            }
            return in;
        };
};
template <class ClassName>
bool operator==(MyVector<ClassName> &First,MyVector<ClassName> &Second){
    if(First.ArraySize!=Second.ArraySize){
        return false;
    }
    for( int i=0;i<First.ArraySize;i++){
        if(First.ArrayVector[i]!=Second.ArrayVector[i]){
            return false;
        }
    }
    return true;
}
template <class ClassName>
bool operator!=(MyVector<ClassName> &First,MyVector<ClassName> &Second){
    return not(First==Second);
}
QapFUc
  • 3
  • 1
  • `MyMatrix operator = (MyMatrix other)` -- `operator =` should be returning a reference to the current object, not a brand new object. Second, it just takes calls to `swap` to implement the `operator=` successfully using [copy/swap](https://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom), and not the confusing code you have now -- Probably reduces it down to a single swap call. Look at your copy constructor -- it is 99% a duplicate of your assignment operator. – PaulMcKenzie May 19 '22 at 14:03
  • `MyMatrix& operator={ std::swap(other.ArraySize_x, ArraySize_x); std::swap(other.ArraySize_y, ArraySize_y); std::swap(other.ArrayMatrix, ArrayMatrix); return *this;}` -- That's all for the assignment operator, but that requires your copy constructor and destructor to be non-buggy, which you need to verify. – PaulMcKenzie May 19 '22 at 14:10
  • 1
    Then your `MyVector::operator=` should not be picking and choosing what should or should not be copied, IMO. When a programmer utilizes `=`, they mean it, i.e. they want to replace the contents of the left hand side of the `=` with the contents of the right hand side of the `=`. Instead, your code just kicks them out if the sizes are different, totally going against what assignment operator should do. An assignment operator's job is one thing, and that is to assign, nothing more, nothing less. The same copy/swap technique can be used here also. – PaulMcKenzie May 19 '22 at 14:17
  • 1
    Also, your `main` should have hard-coded the data in for `yy` and `y` -- there should be no `cin` statements if you want others to duplicate the issues you are seeing (what if someone wants to populate the matrix using a different means other than keyboard input)?. And add to that, you should be passing `other` by const reference in those arithmetic functions, not by value. If your copy constructor is buggy, then the error manifests all over the place by passing by value. – PaulMcKenzie May 19 '22 at 14:27
  • Your matrix times vector overload should return a vector which would side-step your problem I believe. You should really add the size of the matrix and vector as template argument. Make it part of the type so it will be impossible to assign, add, multiply, ... matrixes and vectors of the wrong dimensions. It's safer and faster. – Goswin von Brederlow May 19 '22 at 14:34
  • `MyMatrix operator = (MyMatrix other)` makes no sense. Remove that completely and instead implement move assignment: `MyMatrix operator = (MyMatrix&& other)`. – Goswin von Brederlow May 19 '22 at 14:37
  • @PaulMcKenzie Please point out to me my mistakes in writing the copy constructor – QapFUc May 19 '22 at 17:07
  • @QapFUc It's your assignment operators that are faulty. The only issue I see with your copy constructor is this: `ArrayMatrix[i][j]=0;` -- This will fail if the `ClassName` cannot be (safely) assigned 0. – PaulMcKenzie May 19 '22 at 17:15

0 Answers0