【问题标题】:How to implement a function on template class while using unique_ptr使用 unique_ptr 时如何在模板类上实现函数
【发布时间】:2022-06-12 21:59:12
【问题描述】:

我是第一次学习 unique_ptr,我有这个任务,我想知道是否有人可以就这方面给我建议和信息。

我在这里的人的帮助下实现了矩阵文件。 :)

ma​​in.cpp [此文件无法编辑]

#include <iostream>
#include <memory>
#include "matrix.h"
#include "symetric_matrix.h"

using namespace std;

int main()
{
    unique_ptr<Matrix<int, 3, 3>> symetric_matrix(new SymetricMatrix<int, 3>(5)); // SymetricMatrix matrix 3*3 with default element equals to 5;

    (*symetric_matrix)(1, 2) = 8;
    cout << (*symetric_matrix)(1, 2) << " " << (*symetric_matrix)(2, 1) << endl; // Should print "8 8"
    cout << (*symetric_matrix)[1][2] << " " << (*symetric_matrix)[2][1] << endl; // Should print "8 8"
(*symetric_matrix)[1][0] = 18;
    cout << (*symetric_matrix)[1][0] << " " << (*symetric_matrix)[0][1] << endl; // Should print "18 18"
}

8 的分配应该以矩阵保持不变的方式进行更改。 ma​​trix.h

#include <exception>

template <class T, int M, int N>
class Matrix
{
private:
    T mat[M][N];
    int rows = M;
    int cols = N;

public:
    // Error class
    class IllegalOperation : public std::exception
    {
    public:
        IllegalOperation(const char *msg) : _msg(msg) {}
        virtual const char *what() const throw() { return _msg.c_str(); };

    private:
        std::string _msg;
    };
    // constructor
    Matrix(int v = 0)
    {
        for (int i = 0; i < M; i++)
        {
            for (int j = 0; j < N; j++)
                mat[i][j] = v;
        }
    }

    // Object Constructor
    template <class T1, int M1, int N1>
    Matrix(const Matrix<T1, M1, N1> &other)
    {
        for (int i = 0; i < M; i++)
        {
            for (int j = 0; j < N; j++)
                mat[i][j] = other(i, j);
        }
    }
    // () overloading
    T &operator()(int i, int j)
    {
        return mat[i][j];
    }

    const T &operator()(int i, int j) const
    {
        return mat[i][j];
    }

    // [] overloading
    T *operator[](int index)
    {
        return mat[index];
    }
    const T *operator[](int index) const
    {
        return mat[index];
    }

    // << overloading
    friend std::ostream &operator<<(std::ostream &os, const Matrix<T, M, N> &L)
    {
        for (int i = 0; i < M; i++)
        {
            for (int j = 0; j < N; j++)
                os << L.mat[i][j] << " ";
            os << "\n";
        }
        return os;
    }

    template <class T1, int M1, int N1>
    Matrix<T, M, N1> operator*(Matrix<T1, M1, N1> const &other);
    template <class T1, int M1, int N1>
    const Matrix<T, M, N1> operator*(Matrix<T1, M1, N1> const &other) const;
    Matrix<T, M, N> operator+(Matrix<T, M, N> const &other);

    Matrix<T, M, N> operator+=(const Matrix<T, M, N> &other);

    // scalar
    // Matrix<T, M, N> operator*(T);

    friend T min(Matrix obj)
    {
        T result = obj.mat[0][0];
        for (int i = 0; i < M; i++)
        {
            for (int j = 0; j < N; j++)
                if (result < obj.mat[i][j])
                    result = obj.mat[i][j];
        }
        return result;
    }

    long double avg() const
    {
        long double result = 0;
        for (int i = 0; i < M; i++)
        {
            for (int j = 0; j < N; j++)
                if (result < mat[i][j])
                    result = result + mat[i][j];
        }
        return result / (M * N);
    }
};

template <class T, int M, int N>
Matrix<T, M, N> Matrix<T, M, N>::operator+(Matrix const &other)
{
    if ((this->rows == other.rows) && (this->cols == other.cols))
    {
        Matrix<T, M, N> resultantMatrix;

        for (auto i = 0; i < this->rows; i++)
        {
            for (auto j = 0; j < this->cols; j++)
            {
                auto &valueFirst = this->mat[i][j];
                auto &valueSecond = other.mat[i][j];

                // if ((additionOverflow(valueFirst, valueSecond)) || (additionUnderflow(valueFirst, valueSecond)))
                //     throw std::out_of_range("Resultant value of matrix is out of range");
                // else
                resultantMatrix(i, j) = valueFirst + valueSecond;
            }
        }
        return resultantMatrix;
    }
    else
        throw IllegalOperation("Matrices cannot be added, sizes do not match");
}

template <class T, int M, int N>
template <class T1, int M1, int N1>
Matrix<T, M, N1> Matrix<T, M, N>::operator*(Matrix<T1, M1, N1> const &other)
{
    std::cout << M << " " << N1;
    if (N == M1)
    {
        Matrix<T, M, N1> resultantMatrix;

        for (auto i = 0; i < this->rows; i++)
        {
            for (auto j = 0; j < this->cols; j++)
            {
                for (auto k = 0; k < this->cols; k++)
                {
                    auto &valueFirst = this->mat[i][k];
                    auto &valueSecond = other(k, j);

                    // if ((additionOverflow(valueFirst, valueSecond)) || (additionUnderflow(valueFirst, valueSecond)))
                    //     throw std::out_of_range("Resultant value of matrix is out of range");
                    // else
                    resultantMatrix(i, j) += valueFirst * valueSecond;
                }
            }
        }
        return resultantMatrix;
    }
    else
        throw IllegalOperation("Matrices cannot be multipled, sizes not compatible");
}

template <class T, int M, int N>
template <class T1, int M1, int N1>
Matrix<T, M, N1> const Matrix<T, M, N>::operator*(Matrix<T1, M1, N1> const &other) const
{
    if (N == M1)
    {
        Matrix<T, M, N1> resultantMatrix;

        for (auto i = 0; i < this->rows; i++)
        {
            for (auto j = 0; j < this->cols; j++)
            {
                for (auto k = 0; k < this->cols; k++)
                {
                    auto &valueFirst = this->mat[i][k];
                    auto &valueSecond = other(k, j);

                    // if ((additionOverflow(valueFirst, valueSecond)) || (additionUnderflow(valueFirst, valueSecond)))
                    //     throw std::out_of_range("Resultant value of matrix is out of range");
                    // else
                    resultantMatrix(i, j) += valueFirst * valueSecond;
                }
            }
        }
        return resultantMatrix;
    }
    else
        throw IllegalOperation("Matrices cannot be multipled, sizes not compatible");
}

template <class T, int M, int N>
Matrix<T, M, N> Matrix<T, M, N>::operator+=(const Matrix<T, M, N> &other)
{
    Matrix<T, M, N> resultantMatrix;

    for (auto i = 0; i < M; i++)
    {
        for (auto j = 0; j < N; j++)
        {
            auto valueFirst = other(i, j);
            this->mat[i][j] = this->mat[i][j] + valueFirst;
        }
    }
    return resultantMatrix;
}

// scalar m * T
template <class T, int M, int N>
Matrix<T, M, N> operator*(const Matrix<T, M, N> &other, T scalar)
{
    Matrix<T, M, N> resultantMatrix;

    for (auto i = 0; i < M; i++)
    {
        for (auto j = 0; j < N; j++)
        {
            auto valueFirst = other(i, j);
            if (scalar == 0)
                resultantMatrix(i, j) = 0;
            // else if ((multiplicationOverflow(valueFirst, scalar)) || (multiplicationUnderflow(valueFirst, scalar)))
            //     throw std::out_of_range("Resultant value of matrix is out of range");
            else
                resultantMatrix(i, j) = other(i, j) * scalar;
        }
    }
    return resultantMatrix;
}

// scalar T *m
template <class T, int M, int N>
Matrix<T, M, N> operator*(T scalar, const Matrix<T, M, N> &other)
{
    Matrix<T, M, N> resultantMatrix;

    for (auto i = 0; i < M; i++)
    {
        for (auto j = 0; j < N; j++)
        {
            auto valueFirst = other(i, j);
            if (scalar == 0)
                resultantMatrix(i, j) = 0;
            // else if ((multiplicationOverflow(valueFirst, scalar)) || (multiplicationUnderflow(valueFirst, scalar)))
            //     throw std::out_of_range("Resultant value of matrix is out of range");
            else
                resultantMatrix(i, j) = other(i, j) * scalar;
        }
    }
    return resultantMatrix;
}

template <class T, int M, int N>
bool operator!=(const Matrix<T, M, N> &other1, const Matrix<T, M, N> &other2)
{
    for (auto i = 0; i < M; i++)
    {
        for (auto j = 0; j < N; j++)
        {
            auto valueFirst = other1(i, j);
            auto valueSecond = other2(i, j);
            if (valueFirst != valueSecond)
                return true;
        }
    }
    return false;
}

symetric_matrix.h

template <class T, int M>
class SymetricMatrix : public Matrix<T, M, M>
{
private:
    T mat[M][M];

public:
    SymetricMatrix(int val)
    {
        for (int i = 0; i < M; i++)
        {
            for (int j = 0; j < M; j++)
                mat[i][j] = val;
        }
    }
};

谁能告诉我如何通过symmetric_matrix file 更改矩阵的两个元素而不更改main.cpp 文件。 通过(*symmetric_matrix)(1, 2) = 8; 操作,它应该改变矩阵[1,2] 和矩阵[2,1] 以保持对称。 我必须在其中使用运算符重载吗?由于是指针,我不确定。

代码只改变了它应该改变的矩阵[1,2]。

对于所有看到我在同一个文件上不断提出问题的人,我深表歉意。我正在努力学习,在来这里之前我也在尝试自己的解决方案,直到我陷入困境。

【问题讨论】:

  • 很明显,只有Matrix 应该有mat。只有一个,在Matrix。是什么让您相信SymmetricMatrix 也需要一个? SymmetricMatrix中的方法必须通过调用Matrix中的方法来实现,才能访问底层矩阵。你的 C++ 教科书中的章节主题是什么,这个练习题来自哪里?为了实现这一点,您应该实现运算符重载。这应该在那里解释。您是否熟悉“运算符重载”的含义?
  • 只存储矩阵的一部分。访问元素时,请检查,确保第一个索引大于或等于第二个索引,如果不是这种情况,请交换实际访问的元素的索引...您确实需要将 () 运算符设为虚拟当然...
  • 不是已经提到过,您需要虚拟继承,并且至少需要一个 virtual 析构函数才能使其正常工作?

标签: c++


猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-21
  • 2010-12-02
相关资源
最近更新 更多