2016-09-15 44 views
0

我正在尝试使用自定义矩阵类与CRTP一起玩。现在我正试图重载ostream运算符,请按照https://msdn.microsoft.com/en-us/library/1z2f6c2k.aspx重载自定义类中的ostream运算符

但是,一切似乎都在编译,但程序从不存在,并在屏幕上不显示任何内容。正在发生的事情,我正在挠头。

无论如何,这是相关的代码(对不起是有点冗长)

#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 

整个程序正在使用编译克++ 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方法()。这按预期工作。

不幸的是,调试器没有提供任何有用的信息,因为程序停在矩阵(i,0)行中,并且当我停止程序检索信息时,它说无法获取帧(Clion as调试器)

+0

模板往往很长且复杂且一般难以阅读和理解的错误,但如果您可以将完整的错误输出(作为文本完整且无需编辑)复制粘贴到你的问题的身体。将其格式化为代码。 –

+0

根本没有错误代码。该程序编译并运行,但从不打印出任何东西并永不退出 –

+1

在调试模式下逐步执行代码以查看调用堆栈,但它看起来像您的operator()调用导致无限递归 – wasthishelpful

回答

1

(成员函数MatrixBaseoperator()无条件地自行调用自己,所以是无限递归的。

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。更好的是,使用标准容器。

+0

A !!!!!这是一个非常愚蠢的问题!现在我看到了问题!谢谢! –