代码之家  ›  专栏  ›  技术社区  ›  Dacav

嵌套模板和构造函数

  •  0
  • Dacav  · 技术社区  · 14 年前

    编辑 : 请注意,我在这里的最终目的不是让课程正常工作,而是学习更多关于模板的知识:-)

    template <typename T>
    class Vector
    {
        public:
            Vector(size_t dim) {
                dimension = dim;
                elements = new T[dim];
            }
            /* Here more stuff, like operator[] etc... */
        private:
            size_t dimension;
            T * elements;
    }
    

    template <typename T>
    class Matrix : public Vector<Vector<T> >
    {
        /*...*/
    }
    

    问题来了:在构造函数中,我需要提供行和列作为内部向量的参数。应该是这样的

    template <typename T>
    Matrix<T>::Matrix (size_t ncols, size_t nrows)
             : Vector<Vector<T> > /* Here I need to specify size for both
                                   * internal and external vectors */
    {
    }
    

    显然我不会写字 Vector<Vector<T>(nrows)>(ncols) ,但那正是我所需要的!

    一个可能的解决方案是在模板中包含大小:

    template <typename T, size_t N>
    class Vector
    {
        public:
            Vector() {
                elements = new T[N];
            }
            /* Here more stuff, like operator[] etc... */
        private:
            T * elements;
    }
    

    Vector 应声明为

    template <typename T, size_t N>
    void foo (Vector<T,N> &vec) {...}
    

    你有更好的解决办法吗?

    编辑:

    作为解决方案,我从Fooz先生和chubsdad的帖子中得到了灵感。我就是这样解决问题的:

    /* The RowAccess class is just an array wrapper which raises an exception
     * if you go out of bounds */
    template <typename T>
    class RowAccess
    {
        public:
    
            RowAccess (T * values, unsigned cols) : values(vals), cols(c) {}
    
            T & operator[] (unsigned i) throw (MatrixError) {
                if (i < cols) return values[i];
                else throw MatrixError("Column out of bound");
            }
    
        private:
            T * values;
            unsigned cols;
    };
    
    template <typename T>
    class Matrix
    {
        public:
            Matrix (unsigned rows, unsigned cols) {...}
            virtual ~Matrix () {...}
    
            RowAccess<T> operator[] (unsigned row) {
                if (row < rows) return RowAccess<T>(values + cols * row, cols);
                else throw MatrixError("Row out of boundary");
            }
    
        private:
            unsigned rows;
            unsigned cols;
            T * values;
    };
    

    非常感谢大家!

    4 回复  |  直到 14 年前
        1
  •  1
  •   Mr Fooz    14 年前

    这并不是您所要求的,但是很有可能矩阵最好作为一个单一的线性向量来实现,您可以提供执行索引的高级访问方法(例如elmLoc=row*ncols+col)。这样就不需要创建和初始化向量向量。您也不必担心意外地拥有一些大小不同的内部向量。我使用过的所有密集矩阵实现都使用单个线性向量作为底层实现。

        2
  •  3
  •   Chubsdad    14 年前

    在OO术语中,我将投票支持矩阵和向量之间的“has”关系。矩阵有向量,而不是矩阵是向量,这意味着矩阵不应该从向量派生。

    编辑1:一个小的修正“。。这意味着矩阵不应该“公开地”从向量中导出。私人继承也许还可以。

        3
  •  2
  •   Johannes Schaub - litb    14 年前

    使用这种新的放置方式(埋在 uninitialized_fill

    template <typename T>
    class Vector
    {
        public:
            Vector(size_t dim, T const& c = T()) {
                dimension = dim;
                elements =
                  static_cast<T*>(operator new(sizeof(T) * dim));
                std::uninitialized_fill(elements, elements + dim, c);
            }
            /* Here more stuff, like operator[] etc... */
        private:
            size_t dimension;
            T * elements;
    };
    

    然后可以使用 Matrix::Vector(ncols, Vector<T>(nrows)) Vector Vector< Vector<T> > operator delete(elements) 在析构函数里。

    您可能还希望将向量作为一个成员嵌入,我可能更喜欢这样,因为我认为外部向量的所有操作不一定对矩阵都有意义。然后初始化看起来像 m(ncols, Vector<T>(nrows))


    应该指出的是 std::vector

    template <typename T>
    class Vector
    {
        public:
            Vector(size_t dim, T const& c = T()):elements(dim, c)
            { }
        private:
            std::vector<T> elements;
    };
    

    这是一个简单而安全的方法来实现这一点,你可以得到自动内存管理。

        4
  •  0
  •   jpalecek    14 年前

    这取决于您对向量(和矩阵)类的期望。

    或者您希望在运行时确定大小,在这种情况下,我建议添加一个 resize() 函数,该函数允许您根据需要调整构造函数中向量的大小。

    template <typename T>
    class Vector
    {
        public:
            Vector(size_t dim) {
                dimension = dim;
                elements = new T[dim];
            }
            Vector() : dimension(0), elements(0) {} // you need default constructor
            void resize(size_t dim) { // note: this could be implemented a lot better
              T* new_elements=new T[dim];
              for(int i=0; i<dim && i<dimension; i++)
                new_elements[i]=elements[i];
              delete [] elements;
              elements=new_elements; dimension=dim;
            }
            /* Here more stuff, like operator[] etc... */
        private:
            size_t dimension;
            T * elements;
    }
    

    然后您可以调整 Vectors Matrix 循环中的构造函数。

    如果希望在编译时确定向量或矩阵的大小,最好的方法可能是按照建议使用template non-type参数。