Thread: Need Help Please

  1. #1
    Registered User
    Join Date
    Aug 2006
    Posts
    1

    Talking Need Help Please

    Why does it say in my compiler (DevC++ 4.9.9.2) that this program doesn't have numberOfRows and numberOfColumns declared at the Matrix operator part(it uses inheritance)? I don't want to change the format how it is programmed... just please help me fix the error!

    Code:
    #include <cstdlib>
    #include <iostream>
    #include <stdexcept>
    using namespace std;
    
    
    //---------------------------------------
    //Array declaration
    template <class T>
    class Array
    {
    protected:
        T* data;
        unsigned int base;
        unsigned int length;
    public:
        Array ();
        Array (unsigned int, unsigned int = 0);
        ~Array ();
    
        Array (Array const&);
        Array& operator = (Array const&);
    
        T const& operator [] (unsigned int) const;
        T& operator [] (unsigned int);
    
        T const* Data () const;
        unsigned int Base () const;
        unsigned int Length () const;
    
        void SetBase (unsigned int);
        void SetLength (unsigned int);
    };
    //----------------------------------
    //
    template <class T>
    Array<T>::Array () :
        data (new T [0]),
        base (0),
        length (0)
        {}
    
    template <class T>
    Array<T>::Array (unsigned int n, unsigned int m) :
        data (new T [n]),
        base (m),
        length (n)
        {}
        
    template <class T>
    Array<T>::Array (Array<T> const& array) :
        data (new T [array.length]),
        base (array.base),
        length (array.length)
    {
        for (unsigned int i = 0; i < length; ++i)
    	data [i] = array.data [i];
    }
    
    template <class T>
    Array<T>::~Array ()
        { delete [] data; }
        
    template <class T>
    T const* Array<T>::Data () const
        { return data; }
    
    template <class T>
    unsigned int Array<T>::Base () const
        { return base; }
    
    template <class T>
    unsigned int Array<T>::Length () const
        { return length; }
        
    template <class T>
    T const& Array<T>::operator [] (unsigned int position) const
    {
        unsigned int const offset = position - base;
        if (offset >= length)
    	throw out_of_range ("invalid position");
        return data [offset];
    }
    
    template <class T>
    T& Array<T>::operator [] (unsigned int position)
    {
        unsigned int const offset = position - base;
        if (offset >= length)
    	throw out_of_range ("invalid position");
        return data [offset];
    }
    
    template <class T>
    void Array<T>::SetBase (unsigned int newBase)
        { base = newBase; }
    
    template <class T>
    void Array<T>::SetLength (unsigned int newLength)
    {
        T* const newData = new T [newLength];
        unsigned int const min =
    	length < newLength ? length : newLength;
        for (unsigned int i = 0; i < min; ++i)
    	newData [i] = data [i];
        delete [] data;
        data = newData;
        length = newLength;
    }
    
    
    //------------------------------
    //Array2D class declaration
    template <class T>
    class Array2D
    {
    protected:
        unsigned int numberOfRows;
        unsigned int numberOfColumns;
        Array<T> array;
    public:
        class Row
        {
    	Array2D& array2D;
    	unsigned int const row;
        public:
    	Row (Array2D& _array2D, unsigned int _row) :
    	    array2D (_array2D), row (_row) {}
    	T& operator [] (unsigned int column) const
    	    { return array2D.Select (row, column); }
        };
    
    
        Array2D (unsigned int, unsigned int);
        T& Select (unsigned int, unsigned int);
    
    
        Row operator [] (unsigned int row)
        {  
            return Row (*this, row);
        }
     
        
        
    };
    //-----------------------------------
    //
    template <class T>
    Array2D<T>::Array2D (unsigned int m, unsigned int n) :
        numberOfRows (m),
        numberOfColumns (n),
        array (m * n)
        {}
    
    template <class T>
    T& Array2D<T>::Select (unsigned int i, unsigned int j)
    {
        if (i >= numberOfRows)
    	throw out_of_range ("invalid row");
        if (j >= numberOfColumns)
    	throw out_of_range ("invalid column");
        return array [i * numberOfColumns + j];
    }
    
        
    //------------------------------
    //
    template <class T>
    class Matrix : public Array2D<T>
    {
    public:
        Matrix (unsigned int, unsigned int);
        Matrix operator * (Matrix const&) const;
        //Matrix operator + (Matrix const&) const;
    };
    //-------------------------------
    //
    template <class T>
    Matrix<T> Matrix<T>::operator * (Matrix<T> const& arg) const
    {
        if (numberOfColumns != arg.numberOfRows)
    	throw invalid_argument ("incompatible matrices");
        Matrix<T> result (numberOfRows, arg.numberOfColumns);
        for (unsigned int i = 0; i < numberOfRows; ++i)
        {
    	for (unsigned int j = 0; j < arg.numberOfColumns; ++j)
    	{
    	    T sum = 0;
    	    for (unsigned int k = 0; k < numberOfColumns; ++k)
    		sum += (*this) [i][k] * arg [k][j];
    	    result [i][j] = sum;
    	}
        }
        return result;
    }
    //-------------------------
    //
    int main(int argc, char *argv[])
    {
        Matrix <int> x(10,20);
        system("PAUSE");
        return EXIT_SUCCESS;
    }
    
    //thanks!

  2. #2
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    I think the problem is with the templates. Though, I'm sure there are more suitable answers, I was able to fix this by preceding the variables with this->. I always thought the this pointer was understood, but apparently not with templates.
    Sent from my iPadŽ

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    The code compiles fine for me. What line is the error on? The only error I get is a linker error since the first Matrix constructor is never defined in that code.

    >> I always thought the this pointer was understood, but apparently not with templates.
    It is with templates as well, that shouldn't fix the compile with proper code, although it is possible that a member variable that is accidentally hidden by a local variable shows up again when you do that.

    Edit: I just realized that the matrix operator* won't even be compiled if it is not used. I added code to main to use it and got unrelated compile errors. Are you sure that's the exact code you're using?
    Last edited by Daved; 08-22-2006 at 11:30 AM.

  4. #4
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    The this-> fix is the correct one. This is one of the consequences of two-phase lookup.

    In short, the compiler doesn't search base classes that depend on a template parameter for unqualified names. That's why you need to make the this-> explicit.
    The idea is to allow the compiler to diagnose errors while parsing the template instead of instantiating it. Otherwise, every unqualified invocation would have to be delayed until instantiation, because a dependent base class just might, given a specialization for the current template parameter, define any symbol at all.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed