class Vector3
{
private:
double d[3];
...
};
class Matrix3x3
{
private:
double A[3][3];
...
};
|
This Matrix * Vector operator function is not allowed to access the private variables:
class Vector3
{
private:
double d[3];
...
};
class Matrix3x3
{
private:
double A[3][3];
...
};
Vector3 operator* ( Matrix3x3 m, Vector3 & v)
{
Vector3 out;
for (i = 0; i < 3; i = i + 1)
{
out.d[i] = 0.0; // Not allowed !!!
for (k = 0; k < 3; k = k + 1)
out.d[i] = out.d[i] + m.A[i][k] * v.d[k];
// Not allowed !!!
}
}
|
Because:
Compile with:
CC -c Friend-1.C |
Compilation will result in these errors:
out.d[i] = 0.0; Error: d is not accessible from operator*(Matrix3x3&, Vector3&) out.d[i] = out.d[i] + A[i][k] * v.d[k]; Error: d is not accessible from operator*(Matrix3x3&, Vector3&) Error: A is not accessible from printM(Matrix3x3*) |
NOTE:
Eventhough the variable is the scope, the access is denied based on access qualification (not enough "right of access")
Example:
The Matrix * Vector member operator function is not allowed to access the private variable d[] in Vector3:
class Vector3
{
private:
double d[3];
...
};
class Matrix3x3
{
private:
double A[3][3];
Vector3 operator* ( Vector3 & v)
{
Vector3 out;
for (i = 0; i < 3; i = i + 1)
{
out.d[i] = 0.0; // Not allowed...
for (k = 0; k < 3; k = k + 1)
out.d[i] = out.d[i] + A[i][k] * v.d[k];
// Not allowed...
}
}
};
|
Because:
Compile with:
CC -c Friend-2.C
|
Compilation will result in these errors:
out.d[i] = 0.0; Error: d is not accessible from Matrix3x3::operator*(Vector3&) out.d[i] = out.d[i] + A[i][k] * v.d[k]; Error: d is not accessible from Matrix3x3::operator*(Vector3&) |
class Vector3
{
private:
double d[3];
...
friend Vector3 operator* ( Matrix3x3 &m, Vector3 & v);
// Allows operator*() to access "d[]"
};
class Matrix3x3
{
private:
double A[3][3];
...
friend Vector3 operator* ( Matrix3x3 &m, Vector3 & v);
// Allows operator*() to access "A[][]"
};
|
CC -c Friend-3.C
|
(because there is no main function)
There is one little problem with the program:
friend Vector3 operator* ( Matrix3x3 &m, Vector3 & v); line 9: Error: Matrix3x3 is not defined. |
The compiler complains about this problem:
class Vector3
{
private:
double d[3];
...
friend Vector3 operator* ( Matrix3x3 &m, Vector3 & v);
^^^^^^^^^^^^ undefined !!!
// Allows operator*() to access "d[]"
};
class Matrix3x3 // <----- Matrix3x3 definition
{
private:
double A[3][3];
...
friend Vector3 operator* ( Matrix3x3 &m, Vector3 & v);
^^^^^^^^^^^^ it is now defined...
// Allows operator*() to access "A[][]"
};
|
class Matrix3x3
{
private:
double A[3][3];
...
friend Vector3 operator* ( Matrix3x3 &m, Vector3 & v);
^^^^^^^^^^^^ undefined !!!
// Allows operator*() to access "A[][]"
};
class Vector3
{
private:
double d[3];
...
friend Vector3 operator* ( Matrix3x3 &m, Vector3 & v);
^^^^^^^^^^^^ it is now defined...
// Allows operator*() to access "d[]"
};
|
class classname ; |
A declaration informs the compiler of the type of a variable
A declaration does NOT convey information about its structure
A class declaration is an incomplete class definition - lacking information about its structure
|
Example:
class myClass; // Class declaration |
Compile with:
CC -c Declare.C
|
(because there is no main function)
Example:
class myClass; // Class declaration // "Incomplete definition" |
You will get a compilation error...
class Matrix3x3; // <--- Declare class Matrix3x3
class Vector3
{
private:
double d[3];
...
friend Vector3 operator* ( Matrix3x3 &m, Vector3 & v);
^^^^^^^ NO compilation errors !!!
};
class Matrix3x3
{
private:
double A[3][3];
...
friend Vector3 operator* ( Matrix3x3 &m, Vector3 & v);
// Allows operator*() to access "A[][]"
};
|
CC -c Friend-3a.C
|
(because there is no main function)
NO compile errors...
Example:
class Matrix3x3;
class Vector3
{
private:
double d[3];
friend Vector3 operator* ( Matrix3x3 &m, Vector3 & v);
friend ostream & operator<< (ostream & output, Vector3 & v);
friend int main(int argc, char *argv[]);
};
class Matrix3x3
{
private:
double A[3][3];
friend Vector3 operator* ( Matrix3x3 &m, Vector3 & v);
friend ostream & operator<< (ostream & output, Matrix3x3 & m);
friend int main(int argc, char *argv[]);
};
|
|
We need to jump through another kind of hoop to avoid type check errors !!!
class Matrix3x3
{
private:
double A[3][3];
// We don't need:
//
// friend Vector3 operator* ( Vector3 & v );
//
// because member functions can access
// private variables in its own class
public:
Vector3 operator* ( Vector3 & v )
{
Vector3 out;
int i, k;
for (i = 0; i < 3; i = i + 1)
{
out.d[i] = 0.0;
for (k = 0; k < 3; k = k + 1)
out.d[i] = out.d[i] + A[i][k] * v.d[k];
}
return(out);
}
};
|
NOTE:
| We do NOT need to make operator* () into a friend function of the class Matrix3x3 because all member functions of the class Matrix3x3 have access to the private variable A[][] |
myClass::funcname()
|
class Vector3
{
private:
double d[3];
friend Vector3 Matrix3x3::operator* ( Vector3 & v );
};
|
class Matrix3x3;
class Vector3
{
private:
double d[3];
friend Vector3 Matrix3x3::operator* ( Vector3 & v );
};
|
Compile with:
CC -c Friend-5.C |
Error: In this declaration "*" is of an incomplete type "Matrix3x3" |
Because:
class Matrix3x3;
class Vector3
{
private:
double d[3];
friend Vector3 Matrix3x3::operator* ( Vector3 & v );
^^^^^^^^^^^^^^^^^^^^^
};
|
The compiler complaints because we reference a member (function) inside Matrix3x3
|
To resolve this reference, the compiler
needs to know
structure of Matrix3x3
OK, let's put Matrix3x3 before Vector3 |
class Vector;
class Matrix3x3
{
private:
double A[3][3];
public:
Vector3 operator* ( Vector3 & v )
{
Vector3 out;
int i, k;
for (i = 0; i < 3; i = i + 1)
{
out.d[i] = 0.0;
for (k = 0; k < 3; k = k + 1)
out.d[i] = out.d[i] + A[i][k] * v.d[k];
}
return(out);
}
};
|
Compile with:
CC -c Friend-5a.C |
Error: In this declaration "out" is of an incomplete type "Vector3" |
Because:
class Vector3;
class Matrix3x3
{
private:
double A[3][3];
public:
Vector3 operator* ( Vector3 & v )
{
Vector3 out; // <----- Variable definition
// Vector3 is only declared....
int i, k;
for (i = 0; i < 3; i = i + 1)
{
out.d[i] = 0.0;
for (k = 0; k < 3; k = k + 1)
out.d[i] = out.d[i] + A[i][k] * v.d[k];
}
return(out);
}
};
|
The compiler complaints because we defined a variable using an incompletely defined class Vector3
| To avoid this definition, we use separating class definition and class implementation |
class Vector;
class Matrix3x3
{
private:
double A[3][3];
public:
Vector3 operator* ( Vector3 & v );
// Function implementation is found elsewhere !!
};
|
Compile with:
CC -c Friend-6.C |
No errors !
There is a simpler way to make private variables accessible to member functions of another class:
| friend class |
| friend class |
friend class |
class Vector3
{
private:
double d[3];
...
};
class Matrix3x3
{
private:
double A[3][3];
Vector3 operator* ( Vector3 & v )
{
Vector3 out;
for (i = 0; i < 3; i = i + 1)
{
out.d[i] = 0.0;
for (k = 0; k < 3; k = k + 1)
out.d[i] = out.d[i] + A[i][k] * v.d[k];
}
}
};
|
Can be resolved by making Matrix3x3 into a friend class of Vector3
class Vector3
{
private:
double d[3];
...
friend class Matrix3x3;
};
class Matrix3x3
{
private:
double A[3][3];
Vector3 operator* ( Vector3 & v)
{
Vector3 out;
for (i = 0; i < 3; i = i + 1)
{
out.d[i] = 0.0;
for (k = 0; k < 3; k = k + 1)
out.d[i] = out.d[i] + A[i][k] * v.d[k];
}
}
};
|
Compile with:
CC -c Friend-7.C |