Silver wrote:

It's the cross product. I forget to mention it!

(The program doesn't actually do something useful. It's only an exercise

given to me. )

Thx!

Quick question: What type of product is a * b supposed to give? Is

that a cross product? I will be grateful if you clarify.

> One more thing. I read that it's a good practise to use the keyword

> const "wherever is possible". How much true is that? I have the

> feeling that I 'm not using it in the right way.

Don't worry about it. Some folks believe (mistakenly) that "const"

enables certain compiler optimizations. It does nothing of the kind,

since casts can override const. The const keyword is primarily useful

for three purposes:

1) As a promise to the caller of a function that you will not change an

argument that has been passed by reference.

2) To cause a compile-time error when an object is used in an

inappropriate way.

3) To let a method of a const object be called.

Hth,

Jeff

Here's what I think you wanted. This implementation is naive; it does

not check for I/O stream failures, integer oveflow, etc. I replaced

class A with Matrix, since "A" isn't particularly meaningful. :) I got

rid of B altogether (not sure what purpose it served), and replaced your

dynamically allocated array of dynamically allocated arrays with a

vector of vectors. (In my own code, I typically use only one vector for

all elements, and access element i,j of matrix A_m,n as vector[ i * n +

j ]. Some folks prefer to use standard valarrays and slices. )

I noticed that in your code, your response to errors was to exit the

program, wherever you happened to be. I've replaced this technique with

some basic, exception-based error-handling, just to give you the idea.

Exceptions are usually better, mainly because the appropriate

destructors can be called. For example, if an exception is thrown in

this program, the vectors used to store the matrix will have a chance to

free the memory they've been allocated. In your original code, the

dynamically allocated memory would not be freed, and may or may not have

been reclaimed, depending on the OS where the program was run.

I understand that this is just an exercise; that's great. For me, at

least, writing and reading code is essential to improving. If you

actually needed matrix cross products for a "real" program, though, you

wouldn't need to write them yourself. There are plenty of well-tested,

efficient matrix libraries available. Google for details.

Hth,

Jeff

#include <iostream>

#include <iomanip>

#include <new>

#include <vector>

namespace Silver

{

/* Represents a matrix of m rows and n columns.

*/

class Matrix

{

public:

typedef std::vector< int > Row;

typedef std::vector< Row > Row_Vector;

Matrix( int m =0, int n =0 );

Row& operator [ ] ( int row );

Row const& operator [ ] ( int row ) const;

Matrix const& operator *= ( Matrix const& other );

int m( ) const;

int n( ) const;

void resize( int m, int n );

private:

Row_Vector m_rows;

};

// Outer (cross) product.

Matrix const operator * ( Matrix const&, Matrix const& );

std::ostream& operator << ( std::ostream&, Matrix const& );

}

int Silver::Matrix::m( ) const

{

return m_rows.size( );

}

int Silver::Matrix::n( ) const

{

return m_rows.front( ).size( );

}

Silver::Matrix::Row&

Silver::Matrix::operator [ ] ( int row )

{

return m_rows[ row ];

}

Silver::Matrix::Row const&

Silver::Matrix::operator [ ] ( int row ) const

{

return m_rows[ row ];

}

Silver::Matrix const&

Silver::Matrix::operator *= ( Silver::Matrix const& other )

{

return *this = *this * other;

}

Silver::Matrix::Matrix( int m, int n )

try

{

resize( m, n );

}

catch( std::bad_alloc x )

{

throw std::string( "Silver::Matrix::Matrix( int n ): "

"Not enough memory is available." );

}

catch( std::string s )

{

throw std::string( "Silver::Matrix::Matrix( int n ): " ) + s;

}

catch( ... )

{

throw std::string( "Silver::Matrix::Matrix::( int n ): "

"unexpected exception" );

}

void Silver::Matrix::resize( int new_m, int new_n )

try

{

if( new_m < 0 or new_n < 0 )

{

throw std::string( "matrix dimensions cannot be negative" );

}

Row_Vector new_rows = m_rows;

new_rows.resize( new_m );

for( int row = 0; row < new_m; ++row )

{

new_rows[ row ].resize( new_n );

}

m_rows.swap( new_rows );

}

catch( std::bad_alloc x )

{

throw std::string( "Silver::Matrix::resize( int m, int n ): "

"Not enough memory is available." );

}

catch( std::string s )

{

throw std::string( "Silver::Matrix::resize( int m, int n ): " )

+ s;

}

catch( ... )

{

throw std::string( "Silver::Matrix::resize( int m, int n ): "

"unexpected exception" );

}

Silver::Matrix const

Silver::operator * ( Silver::Matrix const& a, Silver::Matrix const& b )

try

{

if( a.n( ) != b.m( ) )

{

throw std::string(

"arguments are not conformable for multiplication" );

}

Matrix result( a.m( ), b.n( ) );

for( int row = 0; row < a.m( ); ++row )

{

for( int column = 0; column < b.n( ); ++column )

{

for( int i = 0; i < a.n( ); ++i )

{

result[ row ][ column ] +=

a[ row ][ i ] * b[ i ][ column ];

}

}

}

return result;

}

catch( std::string s )

{

throw std::string( "Silver::operator * ( "

"Silver::Matrix const&, "

"Silver::Matrix const& ): " ) + s;

}

catch( ... )

{

throw std::string( "Silver::operator * ( "

"Silver::Matrix const&, "

"Silver::Matrix const& ): "

"unexpected exception" );

}

std::ostream&

Silver::operator << ( std::ostream& out, Silver::Matrix const& matrix )

{

for( int row = 0; row < matrix.m( ); ++row )

{

out << "[ ";

for( int column = 0; column < matrix.n( ); ++column )

{

out << std::setw( 4 ) << matrix[ row ][ column ] << ' ';

}

out << " ]\n";

}

return out;

}

namespace

{

/* Prompt for values, then populate and display the matrix.

*/

void initialize( Silver::Matrix& matrix, std::string const& name )

{

for( int row = 0; row < matrix.m( ); ++row )

{

for( int column = 0; column < matrix.n( ); ++column )

{

/*

std::cout << name << "[ "

<< row << " ][ "

<< column << " ] = "

<< std::flush;

*/

std::cin >> matrix[ row ][ column ];

}

}

std::cout << name << ":\n" << matrix;

}

}

int main( )

try

{

/*

std::cout << "\nDwse diastash n gia ton pinaka nxn? --> "

<< std::flush;

int size;

std::cin >> size;

*/

int am;

int an;

int bm;

int bn;

std::cout << "Enter a.m, a.n, b.m, and b.n.\n";

std::cin >> am >> an >> bm >> bn;

Silver::Matrix a( am, an );

Silver::Matrix b( bm, bn );

initialize( a, "a" );

initialize( b, "b" );

std::cout << "a * b:\n" << ( a * b ) << '\n';

}

catch( std::string s )

{

std::clog << "error: " << s << '\n';

}

catch( ... )

{

std::clog << "error: unexpected exception\n";

}