[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

2x2 Matrices with operator overloading

Posted on 2009-02-24
46
Medium Priority
?
788 Views
Last Modified: 2012-05-06
Hi EE members,

I have some questions regarding operator overloading in C++. I'm supposed to implement a header file which will do the follow requirements as seen in the attached picture.

I've created the header file, but i'm stuck with what should i do for each of the requirements. Anyone can assist me to getting my solutions? Many thanks.
=========== my 2x2.h file ========================
 
#include <iostream>
using namespace std;
 
class M22 {
 
   int a,b,c,d;
 
   public:
      M22 (int A=1,int B=0, int c=0, int D=1): a(A), b(B), c(C), d(D){}
 
 
   //point (1)
   M22 operator<< () { return "[["+a+","+b+"],["+c+","+d+"]]";}   //output <<
 
   //point (2)
   M22 operator==(const M22 & rhs) { return M22(a==rhs.a, b==rhs.b, c==rhs.c, d==rhs.d);}   //comparison ==
 
   //point (3)
   
   
   //point (4)
   M22 operator+(const M22 & rhs) { return M22(a+rhs.a, b+rhs.b, c+rhs.c, d+rhs.d);}   //Binary +
   M22 operator-(const M22 & rhs) { return M22(a-rhs.a, b-rhs.b, c-rhs.c, d-rhs.d);}   //Binary -
 
   //point (5)
   M22 operator*(const k & rhs) { return M22(k*rhs.a, k*rhs.b, k*rhs.c, k*rhs.d);}   //Scalar multiplication *
 
   //point (6)
   
   //point (7)
	
};
 
=========== test file ========================
 
#include <iostream>
using namespace std;
#include "2x2.h"
 
int main() {
M22 m(1,2,8,0), i;
cout << m << \t << i << endl;
if( !(m==i) ) cout << "m and i are different\n";
cout << +m << \t << -m << endl;
cout << m+i << \t << m-i << endl;
cout << *m << \t << *i << endl;
cout << m*i << \t << i*m << \t << m*m << endl;
cout << 3*m << endl;
cout << m[1][1] << m[1][2] << m[2][1] << m[2][2] << endl;
}
 
=======================================
Expected output:
 
[[1,2],[8,0]] [[1,0],[0,1]]
m and i are different
[[1,2],[8,0]] [[-1,-2],[-8,0]]
[[2,2],[8,1]] [[0,2],[8,-1]]
-16 1
[[1,2],[8,0]] [[1,2],[8,0]] [[17,2],[8,16]]
[[3,6],[24,0]]
1280

Open in new window

1.jpg
0
Comment
Question by:jericho_law
  • 18
  • 14
  • 13
  • +1
46 Comments
 
LVL 53

Expert Comment

by:Infinity08
ID: 23719449
>> but i'm stuck with what should i do for each of the requirements.

If you run the test program, do you get the expected output ? If you do, then your implementation is probably correct. If you don't, then you'll need to modify the implementation where needed.
0
 
LVL 5

Expert Comment

by:migoEX
ID: 23719458
// (1): returns "void", const
cout << "[[" << a << ...

// (2) returns "bool", const
return (a==rhs.a && ...)

// (3) M22 operator+(void) const {return *this;}
M22 operator(void) const {return M22(...);}

// (4) OK, may be "const"

// (5) M22 operator*(int k)
and also declare a global operator (out of the scope of your class)
M22 operator*(int k, M22 &m) { return m * k; }

// (6) int operator*(void) const {return a*d ...; }
binary * - similar to (4)

// (7) overload operator[], return some "proxy" class (representing row) which also overloads operator[] and returns int.
0
 
LVL 53

Accepted Solution

by:
Infinity08 earned 120 total points
ID: 23719564
If you compile the code, you should already find a few problems :

(a) There's a typo in one of the constructor arguments ...

(b) The operator<< should have this signature :

          std::ostream& operator<<(std::ostream &os, const M22 &m);

    and it should be a friend of the M22 class.
    ie. it takes an ostream (where the output should be written) and a reference to the object, and returns that same ostream (so more data can be written to the same stream, when chaining <<'s).
    The implementation of the operator<< should of course write its output to that stream.

(c) The parameter of the operator* is a bit odd ... its type is not what you'd expect. It should probably be an int.

(d) The operator== should return a bool. It's a comparison operator, and the result is a boolean value.

(e) You didn't implement the unary operator+ or the dereference operator, or the multiplication operator for multiplying matrices, or the index operator yet.
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 23721067
Following the advices Infinity gave you, your class should look like
class MR
{
    int a,b;
public:
    MR(int x, int y);
    int operator[](int i);
};
 
class M22 {
 
   int a,b,c,d;
 
public:
   M22 (int A=1,int B=0, int c=0, int D=1): a(A), b(B), c(C), d(D){}
 
 
   //point (1)
   friend std::ostream& operator<< (std::ostream& os, const M22& m22);
 
   //point (2)
   bool operator==(const M22 & rhs);
 
   //point (3)
   M22& operator+ ();  
   
   //point (4)
   M22 operator+(const M22 & rhs);
   M22 operator-(const M22 & rhs);
 
   //point (5)
   M22 operator*(int k);
  
   //point (6)
   int operator*(); 
   M22 operator*(const M22 & rhs);  
 
   //point (7)
   MR operator[](int i) { return (i == 1)? MR(a, b) : MR(c, d);	}
};
 
To point (7):
 
if you have m22[1][2] the first operator[] is M22::operator[] which returns a MR class object (what is constructed by one of the rows of m22). Then the second operator[] is that of class MR wich returns either the first or the second row element. So, the final return is an int as required.
 
 
 
The first [] 

Open in new window

0
 

Author Comment

by:jericho_law
ID: 23722257
Hi guys,

Thanks for all the comments and help. Here's what i managed to change from the very kind help from migoEX, Infinity08 and itsmeandnobodyelse.

I'm not too sure what should i do for the points 3, 6 and 7. How should i do the return?

#include <iostream>
using namespace std;
 
class MR
{
    int a,b;
public:
    MR(int x, int y);
    int operator[](int i);
};
 
class M22 {
 
   int a,b,c,d;
 
public:
   M22 (int A=1,int B=0, int C=0, int D=1): a(A), b(B), c(C), d(D){}
   
 
   //point (1)
   friend std::ostream& operator<< (std::ostream& os, const M22& m22){
      cout << "[[" << a << "," << b << "],[" << c << "," << d << "]]" };
      
   //point (2)
   bool operator==(const M22 & rhs){
      return (a==rhs.a && b==rhs.b && c==rhs.c && d==rhs.d )};
   
 
   //point (3)
   M22& operator+ ();  
   M22& operator- ();
   
   //point (4)
   M22 operator+(const M22 & rhs) { 
      return M22(a+rhs.a, b+rhs.b, c+rhs.c, d+rhs.d);} 
   M22 operator-(const M22 & rhs) { 
      return M22(a-rhs.a, b-rhs.b, c-rhs.c, d-rhs.d);}
 
   //point (5)
   M22 operator*(int k) { 
      return M22(k*a, k*b, k*c, k*d);}
  
   //point (6)
   int operator*(); 
   M22 operator*(const M22 & rhs);  
 
   //point (7)
   MR operator[](int i) { return (i == 1)? MR(a, b) : MR(c, d); }
};

Open in new window

0
 

Author Comment

by:jericho_law
ID: 23722534
Sorry ignore the previous post i made, here's the correct one. How close am i in getting them right?
#include <iostream>
using namespace std;
 
class MR
{
    int a,b;
public:
    MR(int x, int y);
    int operator[](int i);
};
 
class M22 {
 
   int a,b,c,d;
 
public:
   M22 (int A=1,int B=0, int C=0, int D=1): a(A), b(B), c(C), d(D){}
   
 
   //point (1)
   friend ostream &operator<< (ostream &os, const M22 &m22){
      return os << "[[" << m22.a << "," << m22.b << "],[" << m22.c << "," << m22.d << "]]"; }
      
   //point (2)
   bool operator==(const M22 &rhs){
      return (a==rhs.a && b==rhs.b && c==rhs.c && d==rhs.d );}
   
 
   //point (3)
   M22 &operator+ ();  
   M22 &operator- ();
   
   //point (4)
   M22 operator+(const M22 &rhs) { 
      return M22(a+rhs.a, b+rhs.b, c+rhs.c, d+rhs.d);} 
   M22 operator-(const M22 &rhs) { 
      return M22(a-rhs.a, b-rhs.b, c-rhs.c, d-rhs.d);}
 
   //point (5)
   M22 operator*(int k) { 
      return M22(k*a, k*b, k*c, k*d);}
  
   //point (6)
   int operator*(); 
   M22 operator*(const M22 &rhs);  
 
   //point (7)
   MR operator[](int i) { return (i == 1)? MR(a, b) : MR(c, d); }
};

Open in new window

0
 

Author Comment

by:jericho_law
ID: 23722604
I did the test, and i think i only managed to get points 1, 2 and 4 correct.

Anyone can help me with the rest of the points?
0
 

Author Comment

by:jericho_law
ID: 23722942
As of now, i managed to solve points 1,2,4,6.

I'm not sure why my point 5 cannot work. Got the complain that "The operation "int * M22" is illegal."



#include <iostream>
using namespace std;
 
class MR
{
    int a,b;
public:
    MR(int x, int y);
    int operator[](int i);
};
 
class M22 {
 
   int a,b,c,d;
 
public:
   M22 (int A=1,int B=0, int C=0, int D=1): a(A), b(B), c(C), d(D){}
   
 
   //point (1)
   friend ostream &operator<< (ostream &os, const M22 &m22){
      return os << "[[" << m22.a << "," << m22.b << "],[" << m22.c << "," << m22.d << "]]"; }
      
   //point (2)
   bool operator==(const M22 &rhs){
      return (a==rhs.a && b==rhs.b && c==rhs.c && d==rhs.d );}
 
   //point (3)
   M22 &operator+ ();  
   M22 &operator- ();
   
   //point (4)
   M22 operator+(const M22 &rhs) { 
      return M22(a+rhs.a, b+rhs.b, c+rhs.c, d+rhs.d);} 
   M22 operator-(const M22 &rhs) { 
      return M22(a-rhs.a, b-rhs.b, c-rhs.c, d-rhs.d);}
 
   //point (5)
   M22 operator*(int k) { 
      return M22((k*a), (k*b), (k*c), (k*d));}
  
   //point (6)
   int operator*(); 
   M22 operator*(const M22 &rhs) {
      return M22( (a*rhs.a)+(b*rhs.c), (a*rhs.b)+(b*rhs.d), (c*rhs.a)+(d*rhs.c), (c*rhs.b)+(d*rhs.d));}  
 
   //point (7)
   MR operator[](int i) { return (i == 1)? MR(a, b) : MR(c, d); }
};

Open in new window

0
 
LVL 53

Expert Comment

by:Infinity08
ID: 23723008
First, the operator<< should be implemented outside of the class, and only a friend declaration should be inside the class.

>> I'm not too sure what should i do for the points 3, 6 and 7.

(3) are the unary plus and minus operators ... The returned object has to be the same or negated version of the this object resp.

(6) is for the unary * (calculate the determinant), and the binary * (multiplication of a matrix with another matrix).

(7) is for indexing into the matrix. Just like you can do with a 2D array.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 23723118
>> Got the complain that "The operation "int * M22" is illegal."

The operator* you defined is for the matrix on the left-hand side. So :

        M22 m;
        int k;
        M22 n = m * k;

and not for :

        M22 n = k * m;

To support the latter, you need to implement this operator :

        M22 operator*(int k, const M22 &m);
0
 

Author Comment

by:jericho_law
ID: 23723284
Hi infinity08,

What you meant when you said, "First, the operator<< should be implemented outside of the class, and only a friend declaration should be inside the class.". My current implementation is not right?

For the "M22 operator*(int k, const M22 &m);" you mentioned, i got this error:

"Illegal number of arguments for M22::operator*(int, const M22&)."
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 23723406
>> What you meant when you said,

The operator<< should be a global function. And just to make sure that the function has access to the privates of the M22 object passed to it, you make it a friend of the M22 class.

If you are unsure about what friends are and how to use them, check this :

        http://www.parashift.com/c++-faq-lite/friends.html


>> For the "M22 operator*(int k, const M22 &m);" you mentioned, i got this error:

It's not a member of the M22 class. It's a global operator.
0
 

Author Comment

by:jericho_law
ID: 23723819
I'm still not quite clear on point 5 and 7.

Are you able to help me by inserting some codes for that 2 points?
#include <iostream>
using namespace std;
 
class MR
{
    int a,b;
public:
    MR(int x, int y);
    int operator[](int i);
};
 
class M22 {
 
   int a,b,c,d;
 
public:
   M22 (int A=1,int B=0, int C=0, int D=1): a(A), b(B), c(C), d(D){}
   
 
   //point (1)
   friend std::ostream &operator<< (std::ostream &os, const M22 &m22){
      return os << "[[" << m22.a << "," << m22.b << "],[" << m22.c << "," << m22.d << "]]"; }
      
   //point (2)
   bool operator==(const M22 &rhs){
      return (a==rhs.a && b==rhs.b && c==rhs.c && d==rhs.d );}
 
   //point (3)
   M22 &operator+ (){ 
 
      if(a<0){
         a=-1*a;}
      if(b<0){
         b=-1*b;}
      if(c<0){
         c=-1*c;}
      if(d<0){
         d=-1*d;}
      
      return *this;}  
   M22 &operator- () { 
      a=-1*a;
      b=-1*b;
      c=-1*c;
      d=-1*d;
      return *this;}
   
   //point (4)
   M22 operator+(const M22 &rhs) { 
      return M22(a+rhs.a, b+rhs.b, c+rhs.c, d+rhs.d);} 
   M22 operator-(const M22 &rhs) { 
      return M22(a-rhs.a, b-rhs.b, c-rhs.c, d-rhs.d);}
 
   //point (5)
   M22 operator*(int k) { 
      return M22((k*a), (k*b), (k*c), (k*d));}
  
   //point (6)
   int operator*() {
      return ((a*d)-(b*c)); }
   M22 operator*(const M22 &rhs) {
      return M22( (a*rhs.a)+(b*rhs.c), (a*rhs.b)+(b*rhs.d), (c*rhs.a)+(d*rhs.c), (c*rhs.b)+(d*rhs.d));}  
 
   //point (7)
   MR operator[](int i) { return (i == 1)? MR(a, b) : MR(c, d); }
};

Open in new window

0
 

Author Comment

by:jericho_law
ID: 23724426
Need help on point 5 and 7 to achieve the required results.
#include <iostream>
using namespace std;
 
class MR
{
    int a,b;
public:
    MR(int x, int y);
    int operator[](int i);
}; 
 
class M22 {
 
   int a,b,c,d;
 
public:
   M22 (int A=1,int B=0, int C=0, int D=1): a(A), b(B), c(C), d(D){}
   
   int Abs(int Nbr) { return (Nbr >= 0) ? Nbr : -Nbr; }
 
   //point (1)
   friend std::ostream &operator<< (std::ostream &os, const M22 &m22){
      return os << "[[" << m22.a << "," << m22.b << "],[" << m22.c << "," << m22.d << "]]"; }
      
   //point (2)
   bool operator==(const M22 &rhs){
      return (a==rhs.a && b==rhs.b && c==rhs.c && d==rhs.d );}
 
   //point (3)
   M22 operator+ (){ 
	  return M22(Abs(a), Abs(b), Abs(c), Abs(d));} 
   M22 operator- () { 
      return M22(-1*a, -1*b, -1*c, -1*d);}
   
   //point (4)
   M22 operator+(const M22 &rhs) { 
      return M22(a+rhs.a, b+rhs.b, c+rhs.c, d+rhs.d);} 
   M22 operator-(const M22 &rhs) { 
      return M22(a-rhs.a, b-rhs.b, c-rhs.c, d-rhs.d);}
 
   //point (5)
   M22 operator*(int k) { 
      return M22((k*a), (k*b), (k*c), (k*d));}
//   M22 operator*(int k, const M22 &m) { 
//      return M22((k*m.a), (k*m.b), (k*m.c), (k*m.d));}   
  
   //point (6)
   int operator*() {
      return ((a*d)-(b*c)); }
   M22 operator*(const M22 &rhs) {
      return M22( (a*rhs.a)+(b*rhs.c), (a*rhs.b)+(b*rhs.d), (c*rhs.a)+(d*rhs.c), (c*rhs.b)+(d*rhs.d));}  
 
   //point (7)
   MR operator[](int i) { return (i == 1)? MR(a, b) : MR(c, d); }
};

Open in new window

0
 
LVL 53

Expert Comment

by:Infinity08
ID: 23724703
Did you understand what I meant by making the operator<< and operator* (for (5)) global functions, rather than member functions of the M22 class ?
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 23725670
>>>>   friend std::ostream &operator<< (std::ostream &os, const M22 &m22){
>>>>        return os << "[[" << m22.a << "," << m22.b << "],[" << m22.c << "," >>>>                       << m22.d << "]]"; }

the statement "the operator<<  is a global function and not a member function" means that you should have an implementation like

// m22.cpp

...

std::ostream &operator<< (std::ostream &os, const M22 &m22)
{
    os << "[[" << m22.a << "," << m22.b << "],["
        << m22.c << ","  << m22.d << "]]";
    return os;
}

which is outside of any class.

Note, if operator<< was a member function it would be a member of class std::ostream which was the left operand in a statement like

     cout << m22;

and never the member function of the right operand (which always have to be the argument).

C++ gives the option to have an operator defined for std::ostream class WITHOUT needing to add anything to the class std::ostream. These operators are called binary operators cause they take two arguments: the left operand - here the std::ostream& - and the right operand - here the const M22 &.

The friend *declaration* in class M22 is only to have access to the private members. Some compilers would accept a (inline) implemetantion of the global function within class M22 but some will not. In any case it is better to move the implementation to a cpp file as suggested.


.


   
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 23725739
>>>> "Illegal number of arguments for M22::operator*(int, const M22&)."

If you want the k factor to be the left operand of a scalar multiplication with a M22 matrix, you can't make the operator* a member of M22, for the same reasons I explained with operator<<. A member operator never can be member of the right operand class. And int type is a C type (POD plain old data) which is no class type, hence you can't define a member operator for int. So, the only way is to write a global binary operator which takes an int as first argument (left operand) and a const M22& a right operand. You can *declare* it as friend in the class M22 but should move the implementation outside of the class.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 23725852
>>>> Need help on point 7 to achieve the required results.
You need an implementation for

    MR(int x, int y);
    int operator[](int i);

which can be made inline. It is trivial for both. The constructor assigns its both members using the arguments in an initializer list.

The operator[] returns either a or b depending on the argument i which should be either 1 or 2 (you can ignore wrong arguments as I did in M22:operator[] or throw an exception).

The implementations of two [][] index operators is a little bit tricky as C++ doesn't know of operator[][] (two indices). Instead we need the MR class as helper which also has the operator[] defined. Then M22::operator[] return a MR (row) object which now is the object for the second [] so that MR::operator[] was called which returns M22::a or M22::b in case the MR is the first row or  M22::c or M22::d in case the MR is the second row. Look at the construction of the rows in M22::operator[].
0
 

Author Comment

by:jericho_law
ID: 23729543
Hi guys,

I'm lost with the global function implementation for the operator<< and operator*, int k as left operand.

Does it mean that i need to have another .cpp file to do the implementation and then over at my header file, inside class M22, i declare it as friend and overwrite the behaviour of the method "M22 operator*(int k, const M22 &m)"?

If i can only have the header file, how should i go about doing it?

For point 7, i don't understand the logic. Is it better if you guys can put it in coding form and comment the lines of behaviour inside?

Thanks for all your kind help.
0
 

Author Comment

by:jericho_law
ID: 23729889
It seems that when i just declare friend for both the operator<< and operator*, it works and have no complains.

Is it because my compiler is able to accept a (inline) implemetantion of the global function within class M22, mentioned by itsmeandnobodyelse? And since i won't have a .cpp file, is it ok? Or there's another way to implement it in my header file, outside Class M22?

Still stuck with point 7.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 23731603
>> Does it mean that i need to have another .cpp file to do the implementation

Not necessarily another ... just 'a' .cpp file.

>> and then over at my header file, inside class M22, i declare it as friend

Correct. That way the global function has access to the privates of the M22 class.

>> and overwrite the behaviour of the method "M22 operator*(int k, const M22 &m)"?

You don't overwrite anything. A declaration does not have an implementation. You simply put the function signature, and declare it as friend.



>> If i can only have the header file, how should i go about doing it?

If you want only one header file, then by all means, do that. However, the implementations of the (member) functions should really be in a .cpp file, and not in the header file, in order to avoid multiple definition errors when the header file is included more than once.
0
 

Author Comment

by:jericho_law
ID: 23731721
Thanks for the tips. =) Now i'm left with point 7.

Infinity08, are you able to help me with that? I tried searching for other examples online and what i have wasn't really what i want. I can't really relate to what i need for operator with 2 [].

I'm thinking since i have:

MR operator[](int i) { return (i == 1)? MR(a, b) : MR(c, d); }

this returns me either a/b or c/d right?

Then the next step would be to locate to the exact a or b for the first case, c or d for the last case right? And also, how can i determine whether i should call MR[] or M22[]?
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 23732017
>> I can't really relate to what i need for operator with 2 [].

The operator[] in the M22 class will return a row of data.
You'll either need a helper class that represents a row (and that has its own operator[] to return a given element from the row), or you need to return a pointer to the element type, in which case, the built-in operator[] will take care of it.

Note that in the latter case, you have less opportunity to perform sanity checks, so it's not recommended.
0
 

Author Comment

by:jericho_law
ID: 23732137
Hmm, say i used the first way of having a helper class, how should i pass the element to the M22 operator[]?

I thinking this way, but it's just not logical.

MR operator[](int i) { return (i == 1)? MR(a, b) : MR(c, d); }
M22 operator[](int i) { return (i == 1)? MR(a, b) : MR(c, d); }
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 23732161
>> how should i pass the element to the M22 operator[]?

The M22 operator[] takes an index as argument, gets the corresponding row, constructs the helper row object for it, and returns it.
The helper object operator[] also takes an index as argument, gets the corresponding element, and returns it.

That way, when you do :

        M22 m;
        m[i][j];

the m[i] part will result in a helper object, and this helper object is then immediately used with [j]. So, the operators are called in this order :

        m.operator[](i).operator[](j)

where the m.operator[](i) part is an object of type helper object. So, you could split it up :

        HelperObj ho = m.operator[](i);
        ho.operator[](j);

This all happens behind the scenes of course, so all the user does is m[i][j].
0
 

Author Comment

by:jericho_law
ID: 23732239
Hm, let me break it down to clear my doubts:

1. The M22 operator[] takes an index as argument, gets the corresponding row, constructs the helper row object for it, and returns it. [This part get's the row instead of the element. How do i get the row? Constructing the helper row object and returning means?]

M22 operator[](int i) { return (i == 1)? MR(a, b) : MR(c, d); }

2. The helper object operator[] also takes an index as argument, gets the corresponding element, and returns it. [With the following code, did it correctly return the element?]

MR operator[](int i) { return (i == 1)? MR(a, b) : MR(c, d); }


0
 
LVL 53

Expert Comment

by:Infinity08
ID: 23732288
>> How do i get the row? Constructing the helper row object and returning means?

A matrix has several rows. Each row has several elements (one for each column).

The M22 operator[] has to return the i-th row (where i is the index passed as argument). So, it has to construct a helper row object that contains the same elements as the i-th row in the matrix.
Once that helper row object is constructed, it is returned from the M22::operator[] method.


If MR is your helper object, then MR represents a row. For a 2x2 matrix, one row contains two elements (one for the first column, and one for the second column). Depending on the index passed to its operator[], you need to return one of those two elements.

Make sure that the return types of the operator[] methods are correct. First you select a row, then from that row, you select an element.
0
 

Author Comment

by:jericho_law
ID: 23732403
How close am i with this?


MR operator[](int i) { return (i == 1)? MR(a, b) : MR(c, d); }
int operator[](int i, const MR &mr) { return (i == 1)? mr.a : mr.b; }
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 23732501
Getting closer :)

Except that the first should be a member of the M22 class, and the second a member of the MR class. Note that the extra parameter for the second should not be there.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 23732519
>>>> How close am i with this?
Not so close.

First the implementation of M22::operator[] already was correct in the sample I posted.

Second the signature of MR::operator[] also was correct in my sample code, you simply need to add the implementation which can be made inline cause it is a member operator (not a global one).

So you have:

class MR
{
     ...

     int operator[](int i)
     {
          ?
     }

};

what means the operator [] takes an int argument (what is the number within the second pair of brackets) and returns an int what is either the first or second member of the row, i. e. 'a' or 'b'.

So the ? can be replaced by

   if (i==1) return a;
   return b;

or the equivalent

   return (i == 1)? a : b;
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 23732562
>> >>>> How close am i with this?
>> Not so close.

He is ... He's just getting there on his own, trying to understand how it works, rather than just copy it from you ;) Which I applaud heh :) Figuring it out for yourself is so much more rewarding ...
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 23732578
So if you have

   M22 m(1, 2, 3, 4);
   int cell21 = m[2][1];

first M22:operator[]  gets a 2 as argument and returns a MR(3, 4) because that is the second row of the matrix. The MR(3, 4) has a=3 and b=4 as members and when MR::operator[] was called (because of the second pair of brackets which operates on that the M22::operator[] has returned) it gets 1 as argument and therefore returns a (value == 3) what is the return of m[2][1].

0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 23732588
Note the helper object MR(3, 4) is only temporary. It was automatically destroyed after MR::operator[] was called.
0
 

Author Comment

by:jericho_law
ID: 23732593
Thanks, both you guys for guiding me. =)
Here's my revision:

M22 operator[](int i) { return (i == 1)? MR(a, b) : MR(c, d); }
MR operator[](int i) { return (i == 1)? a : b; }

Getting there? I got complains when i compile:

"2x2.h", line 52: Error: M22::operator[](int), returning MR, was previously declared returning M22.
"2x2.h", line 51: Error: Cannot use MR to initialize M22.
"2x2.h", line 52: Error: Cannot use int to initialize MR.

0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 23732601
>>>> Getting closer :)
>>>> Not so close

You should use the good news from Infinity ignoring the bad ones from me ;-)
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 23732609
>>> M22::operator[](int), returning MR, was previously declared returning M22.

check the declaration of  M22::operator[](int). It must return MR and not M22
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 23732618
>> "2x2.h", line 52: Error: M22::operator[](int), returning MR, was previously declared returning M22.

That means you have an inconsistency in signatures for the M22::operator[] method.

Can you show the complete code you use now ?
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 23732627
Oops, I'll leave you to it, Alex - I got to go out for a while anyway ;)
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 23732631
>>> MR operator[](int i) { return (i == 1)? a : b; }
again. MR::operator[] returns an int cause one element of a row is a integer (and not a row).
0
 

Author Comment

by:jericho_law
ID: 23732658
Am i still missing out something?
#include <iostream>
using namespace std;
 
class MR {
    int a,b;
public:
    MR(int x, int y);
    int operator[](int i);
}; 
 
class M22 {
 
   int a,b,c,d;
 
public:
   M22 (int A=1,int B=0, int C=0, int D=1): a(A), b(B), c(C), d(D){}
   
   int Abs(int Nbr) { return (Nbr >= 0) ? Nbr : -Nbr; }
 
   //point (1)
   friend ostream &operator<< (ostream &os, const M22 &m22){
      return os << "[[" << m22.a << "," << m22.b << "],[" << m22.c << "," << m22.d << "]]"; }
      
   //point (2)
   bool operator==(const M22 &rhs){
      return (a==rhs.a && b==rhs.b && c==rhs.c && d==rhs.d );}
 
   //point (3)
   M22 operator+ (){ 
	  return M22(Abs(a), Abs(b), Abs(c), Abs(d));} 
   M22 operator- () { 
      return M22(-1*a, -1*b, -1*c, -1*d);}
   
   //point (4)
   M22 operator+(const M22 &rhs) { 
      return M22(a+rhs.a, b+rhs.b, c+rhs.c, d+rhs.d);} 
   M22 operator-(const M22 &rhs) { 
      return M22(a-rhs.a, b-rhs.b, c-rhs.c, d-rhs.d);}
 
   //point (5)
   friend M22 operator*(int k, const M22 &m) { 
      return M22((k*m.a), (k*m.b), (k*m.c), (k*m.d));}   
  
   //point (6)
   int operator*() {
      return ((a*d)-(b*c)); }
   M22 operator*(const M22 &rhs) {
      return M22( (a*rhs.a)+(b*rhs.c), (a*rhs.b)+(b*rhs.d), (c*rhs.a)+(d*rhs.c), (c*rhs.b)+(d*rhs.d));}  
 
   //point (7)
   M22 operator[](int i) { return (i == 1)? MR(a, b) : MR(c, d); }
   MR operator[](int i) { return (i == 1)? a : b; }
   
};

Open in new window

0
 
LVL 39

Assisted Solution

by:itsmeandnobodyelse
itsmeandnobodyelse earned 80 total points
ID: 23732727
>>>   //point (7)
>>>    M22 operator[](int i) { return (i == 1)? MR(a, b) : MR(c, d); }
>>>    MR operator[](int i) { return (i == 1)? a : b; }
   
Still bad.

the first operator returns MR and the second must be moved up to class MR and returns int.

>>>   //point (5)
>>>    friend M22 operator*(int k, const M22 &m) {
>>>       return M22((k*m.a), (k*m.b), (k*m.c), (k*m.d));}  

make it a declaration only and move the two lines to m22.cpp (or main.cpp or any .cpp you have but only in one).

Include the header m22.h before the implementation and remove the friend keyword (which is only valid for declaration).

Same do with operator<<.
0
 

Author Comment

by:jericho_law
ID: 23732759
Can i not make the implementations at any .cpp? Cause i'm only allowed to change my m22.h file.


0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 23733381
>>>> Cause i'm only allowed to change my m22.h file.

Do you have a m22.cpp at all?

if so, put the operator implementations there. It is the right place.

if not, are you allowed to create one?

if so, create a m22.cpp, include the m22.h and put the operator implementations there. It is the right place. Add the m22.cpp to your project (or makefile).

If not, did you get errors when implementing the friend operators in class M22?

if not you can leave the it as it was but you should know that there are compilers which wouldn't allow that.

if you get errors you have to remove them from class (only leave the friend declaration) and put implementation below class replacing the 'friend' by 'inline' keyword. That way you won't get duplicate module if the m22.h was included by two .cpp files.

0
 

Author Closing Comment

by:jericho_law
ID: 31550474
Great help! =)
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 23733646
Which option did you choose for the global operators?
0
 

Author Comment

by:jericho_law
ID: 23733687
I left it with the header. Cause i'm not allowed to actually implement anything in the main.cpp nor can i create another .cpp. My compiler works well and since i'm not given much choice, i will state my reasons if the code fails at another compiler or machine. Thanks! =)
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.
Suggested Courses

834 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question