Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How Can I Overload this? 1

Status
Not open for further replies.

sedawk

Programmer
Feb 5, 2002
247
US
I have two header files: MyVector.h and MyMatrix.h. In both of them I define two multiplication function with the same name. Of course, the parameters are different:

Code:
template <class Type>
Vector<Type> mult(const Vector<Type>& v1, const Vector<Type>& v2);
for vector multiplication, and

Code:
template <class Type>
Matrix<Type> mult(const Matrix<Type>& m1,const Matrix<Type>& m2);

They both work on either matrix or vector. Now I need to define a matrix-vector multiplication, ie.,
Code:
template <class Type>
Type MatVetmult(const Matrix<Type>& m1, const Vector<Type> v2)

In this function prototype, I need to extract each row of matrix m1 to do a inner product with vector v2(the inner product define in MyVector.h). I already have a getRow(n) function in MyMatrix.h. Now the problem is when I do this in my MatVetmult(...):

Code:
float temp = mult(m.getRow(1),v2);

VC6++ doesn't recognize it needs to do a vector multiplication but complains that it is an illegal matrix multiplication.

It will be too tedious to modified the function names in all file. I recall something about overloading function but after check "C++ Primer", it looks like I can't overload it with this scope.

Any idea?

Thanks
 
Sorry, I don't understand your problem explanation. I have another problem with your code snippet: no conversion between Vector and float. What type returned from m.getRow()? If it's Vector, mult() returns Vector then assign Vector to float...
 
the returned from m.getRow(int n) is a vector: extract indexed n row from matrix m. Then mult(vector1,vector2) supposed to return a float which is the inner product of vector1 and vector2. The conversion what you are in doubt has already been process in mult(vector1,vector2) if mult() is treated as vector multiplication.

But the problem is that in my code snippet mult() wasn't treated as vector multiplication. It complains error in *matrix* multiplication. So I think I should overload mult(m.getRow(int n),v2) as vector multiplication.
 
In my code sceleton (of your case) the only error is bad (no) conversion from Vector to float (double in my code). I don't understand why you get matrix mult. It seems we have VC++ SP5, don't you?
Proper function selection in C++ based only on signatures (types of parameters), not on return value types.
Can you show some kind of refined code snippet with matrix error source?..
 
It seems something missed: I am not using the standard library <vector.h> but redefine my own libraries: "MyMatrix.h" and "MyVector.h". So in MyVector.h I have a function extracting a certain row, like this:

Code:
/* assume v1 has the same number of column as the matrix
   has 
*/
v1 = m.getRow(2); // get 2nd row of m to v1

Of course, getRow(int n) is just one function in MyMatrix.h, multiplication is one of other matrix operations. It should not relate to VC++ SP too much, right?

 
My 'reconstruction' snippet did not relate to STL vector too:
Code:
template <class T>
class Vector
{
};

template <class T>
class Matrix
{
public:
	Vector<T> getRow(int i) const;
};

template <class Type>
Vector<Type> mult(const Vector<Type>& v1, const Vector<Type>& v2);

template <class Type>
Matrix<Type> mult(const Matrix<Type>& m1,const Matrix<Type>& m2);

template <class Type>
Type MatVetmult(const Matrix<Type>& m1, const Vector<Type> v2);

typedef Vector<double> V;
typedef Matrix<double> M;

int main(int argc, char* argv[])
{
  V	v2;
  M	m;
  double temp = mult(m.getRow(1),v2); // No conversion...
  return 0;
}
You have an error... Show us the code (reduce its size to minimum if possibly). Service packs correct some compiler defects - is it a matter of great importance if you suspect VC++ compiler or not?...
 
Ok, since you insist, here are my MyVector.h and MyMatrix.h files(I truncated other functions not related):

Code:
template <class Type>
class Vector
{
private:
	// Data contained in class Vector
	Type *m_data;

	// Length of the vector
	int m_length;
	void init( int newLen, const Type *newData = NULL )
	{

                // some parameter validations skipped
		
		// Allocate new array
		m_data = new Type[ newLen ];

		// Check if new data was given
		if( newData != NULL )
		{
			// Copy in new data from initialization
			memcpy( m_data, newData, newLen * sizeof( Type ) );
		}
	}
public:
	///////////////////////////////////////////////////////////////////////
	//
	// Constructors and Destructor
	//
	///////////////////////////////////////////////////////////////////////
	Vector( int length = 0, const Type *newData = NULL ) :
		m_data( NULL ),
		m_length( 0 )
	{
		init( length, newData );
	}

	// Copy constructor
	Vector( const Vector<Type>& v ) :
		m_data( NULL ),
		m_length( 0 ) 
	{
		// Construction from existing vector
		init( v.m_length, v.m_data );
	}

	~Vector() { //free memory }

// other functions and operators skipped here.

template <class Type>
Type mult( const Vector<Type>& v1, const Vector<Type>& v2 )
{
	int len = min( v1.length(), v2.length() );
	if( len == 0 )
		throw DSPBoundaryException( "Vector has no data" );
	Type t = (Type)0;
	for( int i = 0; i < len; i++ )
		t += v1[i] * v2[i];
	return t;
}

Matrix class:
Code:
template <class Type>
class Matrix
{
private:
	// Data contained in rows
	Type **m_data;

	// Height and width of the matrix
	int m_rows;
	int m_cols;
	void init( int rows, int cols, Type **newData = NULL )
	{
	void init( int rows, int cols, Type **newData = NULL )
	{
		
		m_data = new Type*[rows];
		m_rows = rows;
		m_cols = cols;
                
                // parameter validation skipped

		// Allocate each row
		for( int i = 0; i < m_rows; i++ )
		{
			m_data[i] = new Type[m_cols];
                }
		// Fill array if data given
		if( newData != NULL )
		{
			for( i = 0; i < m_rows; i++ )
				memcpy( m_data[i], newData[i], cols * sizeof( Type ) );
		}
	}
public:
	///////////////////////////////////////////////////////////////////////
	//
	// Constructors and Destructor
	//
	///////////////////////////////////////////////////////////////////////
	Matrix( int rows = 0, int cols = 0 ) :
		m_data( NULL ),
		m_rows( 0 ),
		m_cols( 0 )
	{
		init( rows, cols );
	}

	// Copy constructor
	Matrix( const Matrix<Type>& m ) :
		m_data( NULL ),
		m_rows( 0 ),
		m_cols( 0 )
	{
		// Construction from existing matrix
		init( m.m_rows, m.m_cols, m.m_data );
	}

	// Destructor
	~Matrix() { //free memory }
	// Return a matrix row as a Vector<Type>
	const Vector<Type> getRow( int row ) const
	{
		Vector<Type> v( m_cols, m_data[row] );
		return v;
	}
template <class Type>
Matrix<Type> mult( const Matrix<Type>& m1, const Matrix<Type>& m2 )
{
	int rows = m1.rows();
	int cols = m2.cols();

	Matrix<Type> mRet( rows, cols );
	for( int i = 0; i < rows; i++ )
	{
		for( int j = 0; j < cols; j++ )
		{
			Type tsum = 0;
			for( int k = 0; k < m1.cols(); k++ )
				tsum += m1[i][k] * m2[k][j];
			mRet[i][j] = tsum;
		}
	}
	return mRet;
}

So the two mulitplications have the same name but with different return structures: Type and Matrix.
 
Now I insert your classes in my test bed, add length(), operator [] and exception class declaration then compile this snippet:
Code:
int main(int argc, char* argv[])
{
  Matrix<double> m(2,2);
  Vector<double> v(2);
  double temp = mult(m.getRow(1),v);
  cout << temp << endl;
  return 0;
}
That's all right: my VC++ (6.0 SP5;) installation recognizes Vector::mult() in the temp var initialization. Then I have a run-time exception but it's the other story...

Is it exactly your program case or not?. What else we must do to hit target?..
 
>VC6++ doesn't recognize it needs to do a vector multiplication but complains that it is an illegal matrix multiplication.

What? How can C++ determine that? C++ has no idea what a matrix multiplication is. mult is just a (template) function like any other. Exactly what error do you get?

/Per

&quot;It was a work of art, flawless, sublime. A triumph equaled only by its monumental failure.&quot;
 
ArkM,

All right, can you tell what I did wrong here? This is the code I am using to test and the errors are shown after that:

Code:
main()
{
        Matrix<float> A( 3, 3 );

	static float c1[] = {1.0,3.0,2.0};
	Vector<float> c(3,c1);
	A[0][0] = -1.0;	A[0][1] = 2.0;	A[0][2] = 1.0;
	A[1][0] = -2.0;	A[1][1] = 2.0;	A[1][2] = 1.0;
	A[2][0] = -1.0;	A[2][1] = 2.0;	A[2][2] = 3.0;

	float temp = mult(A.getRow(1),c);
	cout << temp << endl;
}

I took the first row of A=[-1,2,1] multiply by c=[1,3,2], it should return 7: I supposed the mult() to do an inner product of row 1 of A and c, so -1*1+2*3+1*2=7. But I got 6. Anything wrong with my test? Go back the very first post, that is why I suspecting mult() didn't do vector multiplication. Anything I missed?
 
I know what was missing: the index in my getRow(int n) is 0-indexed instead of 1-indexed(what's the official term for this). In the above test, in fact, I got the second row: so -2*1+2*3+1*2=6, which is correct. The code lead me to other direction. I need to change the indexing now.

Thanks ArkM, I would not try this if you had not remind the points.
 
Your previous posts sounds like you have compilation error (Matrix::mult() instead of Vector::mult()). In reality it was algorithmic error. The problem behind the problem case...

Now it seems Vector::m_length == 0 in any case after Vector::init(). I can't find m_length proper initialization in Vector class in your snippet above (hope you have this initialization in your true code;).

I think it's better to have 0-based indexing (in spirit of C++ language;), but it's a matter of taste (and this project functional specifications;).

There is another subtle point in your Matrix::init() code. You have declared i variable in the 1st loop header then use it in the 2nd loop w/o declaration. The point is that VC++ treats such inner declaration in old fashion. Now C++ Standard localizes these variables in loop bodies. Make common i declaration outside loop header (in old good C style;) - it's more safety approach.

Good luck!
 
> Make common i declaration outside loop header (in old >good C style;) - it's more safety approach.

Ok, I will take this advice and change my code.

Code:
 // Allocate each row
        int i;      // declare i outside of all loops
        for( i = 0; i < m_rows; i++ )
        {
            m_data[i] = new Type[m_cols];
                }
        // Fill array if data given
        if( newData != NULL )
        {
            for( i = 0; i < m_rows; i++ )
                memcpy( m_data[i], newData[i], cols * sizeof( Type ) );
        }

I do have m_length in my true code but I skipped in the post.

Yeah, in my first post, I did get compilation error. But that is because I could not figure out why my results are correct so I modified here and there to debug. The compilation error was not true one. The main error is the result not correct.

I think in terms computer language, 0-based indexing maybe more conventional, but in this case, 1-based indexing is closer to math convention.

Thanks for your help.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top