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.

Solved

Posted on 2009-02-24

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.

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
```

1.jpg
46 Comments

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.

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.

(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.

```
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 []
```

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); }
};
```

```
#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); }
};
```

Anyone can help me with the rest of the points?

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); }
};
```

>> 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.

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);

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&)."

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

>> 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.

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); }
};
```

```
#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); }
};
```

>>>> 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.

.

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.

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[].

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.

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.

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.

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[]?

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.

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); }

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[]

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].

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); }

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.

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; }

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.

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;

>> 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 ...

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].

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.

>>>> Not so close

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

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

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

Can you show the complete code you use now ?

again. MR::operator[] returns an int cause one element of a row is a integer (and not a row).

```
#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; }
};
```

>>> 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<<.

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.

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

Connect with top rated Experts

**19** Experts available now in Live!