簡體   English   中英

在自定義類中重載ostream運算符

[英]Overloading ostream operator in custom class

我正在嘗試使用帶有自定義矩陣類的CRTP。 現在,我正在嘗試重載ostream運算符,請遵循https://msdn.microsoft.com/zh-cn/library/1z2f6c2k.aspx

但是,所有內容似乎都在編譯,但是該程序從不存在,並且在屏幕上不打印任何內容。 我正在撓頭,正在發生的事情。

無論如何,這是相關的代碼(抱歉,這有點冗長)

#ifndef EXPERIMENT_POINTERMATRIX_H
#define EXPERIMENT_POINTERMATRIX_H

#include <cstdlib>
#include <ostream>
#include "macro.h"
namespace PM {
    template<typename T, typename Derived>
    class MatrixBase{
    public:
        size_t nRow;
        size_t nCol;

        MatrixBase(const size_t nRow_,const size_t nCol_):nRow(nRow_), nCol(nCol_){}
        Derived& derived(){
            return *static_cast<Derived*>(this);
        }
        const Derived& derived() const{
            return *static_cast<Derived*>(this);
        }

        T& operator()(const size_t i, const size_t j){
            CHECK_BOUND(i,j,*this);
            return derived().operator()(i,j);
        }
        const T& operator()(const size_t i, const size_t j) const {
            return const_cast<T&>(
                    static_cast<const MatrixBase<T, Derived>&>(*this).operator()(i,j));

        }

        inline T rows(){
            return nRow;
        }
        const T rows() const {
            return nRow;
        }
        inline T cols(){
            return nCol;
        }
        const T cols() const {
            return nCol;
        }
        template<typename t1, typename t2>
        friend std::ostream& operator<<(std::ostream& os, const MatrixBase<t1, t2> & matrix);
    };
    template<typename t1, typename t2>
    std::ostream& operator<<(std::ostream& os, const MatrixBase<t1, t2>& matrix){

        for (size_t i =0;i<matrix.rows();i++){

            os << matrix(i,0);
            if (matrix.cols()>1) {
                for (size_t j = 1; j < matrix.cols(); j++) {
                    os << "," << matrix(i, j);
                }
            }
            os << std::endl;
        }
        return os;
    };

    template<typename T, typename Derived>
    class Matrix : public MatrixBase<T, Matrix<T, Derived>>{
    public:
        T * data;

        Matrix(const size_t nRow, const size_t nCol):MatrixBase<T, Matrix<T, Derived>>(nRow, nCol){
            data = (T*) malloc(sizeof(T)*nRow*nCol);
        }

        ~Matrix(){
            free(data);
        }
        Derived& derived(){
            return *static_cast<Derived*>(this);
        }
        const Derived& derived() const{
            return *static_cast<Derived*>(this);
        }

        T& operator()(const size_t i, const size_t j){
            return derived().operator()(i,j);
        }


    };

    template<typename T, typename Derived>
    class MatrixView : public MatrixBase<T, MatrixView<T, Derived>>{
    public:
        T * data;
        MatrixView(const size_t nRow, size_t nCol, T * other):MatrixBase<T, MatrixView<T, Derived>>(nRow, nCol), data(other){}
        T& operator()(const size_t i, const size_t j){
            return derived().operator()(i,j);
        }
        Derived& derived(){
            return *static_cast<Derived*>(this);
        }
        const Derived& derived() const{
            return *static_cast<Derived*>(this);
        }
    };

    template<typename T>
    class MatrixRowMajor: public Matrix<T, MatrixRowMajor<T>>{
    public:

        MatrixRowMajor(const size_t nRow, const size_t nCol):Matrix<T, MatrixRowMajor<T>>(nRow, nCol){}
        T& operator()(const size_t i, const size_t j){
            using base = MatrixBase<T, Matrix<T, MatrixRowMajor<T>>>;
            using super = Matrix<T, MatrixRowMajor<T>>;
            return super::data[i*base::nCol+j];
        }
    };
    template<typename T>
    class MatrixColMajor: public Matrix<T, MatrixColMajor<T>>{
    public:
        MatrixColMajor(const size_t nRow, const size_t nCol):Matrix<T, MatrixColMajor<T>>(nRow, nCol){}
        T& operator()(const size_t i, const size_t j){
            using base = MatrixBase<T, Matrix<T, MatrixColMajor<T>>>;
            using super = Matrix<T, MatrixColMajor<T>>;
            return super::data[i+j*base::nRow];
        }
    };
    template<typename T>
    class MatrixViewRowMajor : public MatrixView<T, MatrixViewRowMajor<T>>{
    public:
        MatrixViewRowMajor(const size_t nRow, const size_t nCol, T* other):MatrixView<T, MatrixViewRowMajor<T>>(nRow, nCol, other){}
        T& operator()(const size_t i, const size_t j){
            using base = MatrixBase<T, Matrix<T, MatrixViewRowMajor<T>>>;
            using super = MatrixView<T, MatrixViewRowMajor<T>>;
            return super::data[i*base::nCol+j];
        }
    };

    template<typename T>
    class MatrixViewColMajor : public MatrixView<T, MatrixViewColMajor<T>>{
    public:
        MatrixViewColMajor(const size_t nRow, const size_t nCol, T* other):MatrixView<T, MatrixViewRowMajor<T>>(nRow, nCol, other){}
        T& operator()(const size_t i, const size_t j){
            using base = MatrixBase<T, Matrix<T, MatrixViewRowMajor<T>>>;
            using super = MatrixView<T, MatrixViewRowMajor<T>>;
            return super::data[i+j*base::nRow];
        }
};
}

void test_print(){
    using namespace PM;
    using namespace std;
    MatrixRowMajor<double> matrix(10, 1);
    for (int i =0;i<matrix.rows();i++){
        matrix(i,0)=1.0;
        std::cout << "i'th entry is " <<matrix(i,0) << std::endl; //This is fine
    }
    std::cout << matrix; //This is not fine
}
#endif //EXPERIMENT_POINTERMATRIX_H

整個程序使用g ++ 4.9編譯(啟用c ++ 11)

編輯:為了測試是否是操作員的問題,我創建了以下方法(在MatrixBase上):

void print(){
            for (size_t i =0;i<this->rows();i++){
                std::cout  << this->operator()(i,0);
                if (this->cols()>1) {
                    for (size_t j = 1; j < this->cols(); j++) {
                        std::cout << "," << this->operator()(i, j);
                    }
                }
                std::cout << std::endl;
            }
        }

並調用諸如matrix.print()之類的方法。 這按預期工作。

不幸的是,調試器沒有提供有用的信息,因為該程序在os << matrix(i,0)行中停止,並且當我停止該程序以檢索信息時,它說無法獲取幀(Clion作為調試器)

MatrixBase成員函數) operator()無條件地調用自身,因此它是無限遞歸的。

const T& operator()(const size_t i, const size_t j) const {
        return const_cast<T&>(
                static_cast<const MatrixBase<T, Derived>&>(*this).operator()(i,j));

    }

該函數是尾遞歸的,因此可以導致無限循環,而不是由於較大的調用深度而崩潰。

與您的問題無關,通常不建議在C ++中使用malloc() -特別是在處理可能與C不直接兼容的類型(例如C ++類)時-對於您的類的用戶,取決於類型T可以是不確定的。 請改用new運算符。 更好的是,使用標准容器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM