Inherited operators

May 13, 2010 at 9:18pm
Hey all, here is the problem:
I'm built a Matrix class and I did the dirty work redefining all the boring operators (+,-,* etc.). Now I needed a specifical Vector class, so I decided to let it inherit from Matrix class (as vectors, for the most, should act like n x 1 or 1 x n matrices). So i have, for example, a Matrix operator+ function working this way

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
VMatrix VMatrix::operator+ (const VMatrix &add)
{
	if (rows() == add.rows() && cols() == add.cols())
	{
		VMatrix r(rows(),cols());

		for(int i=0;i<rows();i++)
		{
			for (int j=0;j<cols();j++)
			{
				r[i][j] = m[i][j] + add[i][j];
			}
		}
		return r;
	}
	cout << "Bad operation."<<endl;
	return VMatrix();
}


it obviously does the sum of the two matrices and returns a Matrix element. Now if my Vector class inherits this method is awesome but there is a problem: the sum of two vectors will return a Matrix not a Vector!
This makes lines of code like this

(v1+v2).inline_print() //function implemented *just* in Vector class

uncompilable. And i saw some strange errors like, for example, vectors divided by some constant becoming 0. Is there a clean way to let the Vector class inherit the same operators but with function returning the correct class type? Redefining all operators would make inheriting useless.

Thanks in advance, valleyman
May 13, 2010 at 10:28pm
You have to make sure that a few conditions are met.
Make your operators friend functions, and make sure you have the proper constructors and the like.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <iostream>
using namespace std;

struct point_t
  {
  int x, y;
  point_t( int x = 0, int y = 0 ): x( x ), y( y ) { }
  point_t( const point_t& pt ): x( pt.x ), y( pt.y ) { }
  friend point_t operator + ( const point_t& lhs, const point_t& rhs );
  };

point_t operator + ( const point_t& lhs, const point_t& rhs )
  {
  return point_t( lhs.x + rhs.x, lhs.y + rhs.y );
  }

ostream& operator << ( ostream& outs, const point_t& pt )
  {
  return outs << "(" << pt.x << "," << pt.y << ")";
  }

int gcd( int a, int b )
  {
  if (a == 0)
    return b;

  while (b != 0)
    {
    if (a > b) a -= b;
    else       b -= a;
    }

  return a;
  }

struct coprime_t: public point_t
  {
  coprime_t( int x, int y ): point_t( x, y ) { }
  coprime_t( const point_t& pt ): point_t( pt ) { }
  bool valid() const
    {
    return gcd( x, y ) == 1;
    }
  };

int main()
  {
  coprime_t a( 6, 9 );
  coprime_t b( 0, 4 );
  coprime_t c = a + b;

  cout << a << " is " << (a.valid() ? "coprime\n" : "not coprime\n");
  cout << b << " is " << (b.valid() ? "coprime\n" : "not coprime\n");
  cout << c << " is " << (c.valid() ? "coprime\n" : "not coprime\n");

  return 0;
  }

Good luck!
May 18, 2010 at 8:19pm
Well I defined them correctly - I think - because the above code approximately works.
But instead of

coprime_t c = a + b;

I'd like to be able to use concatenated operators like below

(a + b).coprime_print() // with coprime_print() being a coprime_t specific function

Do I have to redefine all the operators?
Thanks for the help
Last edited on May 18, 2010 at 8:19pm
May 18, 2010 at 8:31pm
I don't see why that wouldn't work... actually now that I read the definitions a bit closer, yes I do.

-Albatross
Last edited on May 19, 2010 at 3:07pm
May 18, 2010 at 9:17pm
Yes, you would have to update the operators, because default type promotion needs to work. There is no default type promotion to figure out what class is meant when you simply add two.

JSYK, using constructs like (a + b).quux() is not a good idea. Be explicit:

1
2
3
4
5
6
foo( a + b ).quux();
//or
{
  foo x = a + b;
  x.quux();
}

Good luck!
May 19, 2010 at 3:01pm

@Albratross:

I don't see why that wouldn't work...

Well it wouldn't because (a+b) returns a point_t object - not coprime_t - and there is no function coprime_print() defined in the point_t class.

@Duoas: I understood, thanks for the very clear explanation. Just a question, for the sake of curiosity,

JSYK, using constructs like (a + b).quux() is not a good idea. Be explicit:


why isn't it a good idea? Just because it brings the above problem or for any other reasons?
May 19, 2010 at 5:12pm
Yes, for the very reasons we have covered, plus it just looks fugly to use a temporary object that way.
May 19, 2010 at 5:54pm
Plus when you compile your code in release mode the temporary vars disappear (most of the time).
May 19, 2010 at 7:25pm
Optimizations are not permitted to change the behavior of the program. When they do, that's a bug in the optimizer.
May 25, 2010 at 7:24pm
Indeed, thanks for the help guys!
Topic archived. No new replies allowed.