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 |