Friend Functions and the this Pointer
A friend function is a function that is not a class member but has access to the class's private and protected members. Friends are declared inside the class with the friend keyword. The use of friends must be prudent because it violates the principle of encapsulation.
The this pointer is an implicit pointer available inside all class member functions. this points to the object that called the function. The this pointer is useful for distinguishing between a class's data members and function parameters with the same name.
Code Example
#include <iostream>
#include <string>
using namespace std;
class Matrix {
private:
int rows, cols;
double** data;
public:
Matrix(int r, int c) : rows(r), cols(c) {
data = new double*[rows];
for (int i = 0; i < rows; i++) {
data[i] = new double[cols];
for (int j = 0; j < cols; j++) {
data[i][j] = 0;
}
}
}
~Matrix() {
for (int i = 0; i < rows; i++) {
delete[] data[i];
}
delete[] data;
}
Matrix& setValue(int r, int c, double val) {
data[r][c] = val;
return *this;
}
friend void printMatrix(const Matrix& m);
friend Matrix addMatrices(const Matrix& a, const Matrix& b);
friend class MatrixPrinter;
};
class MatrixPrinter {
public:
void print(const Matrix& m) {
cout << "Matrix " << m.rows << "x" << m.cols << ":" << endl;
for (int i = 0; i < m.rows; i++) {
for (int j = 0; j < m.cols; j++) {
cout << m.data[i][j] << "\t";
}
cout << endl;
}
}
};
void printMatrix(const Matrix& m) {
cout << "Matrix " << m.rows << "x" << m.cols << ":" << endl;
for (int i = 0; i < m.rows; i++) {
for (int j = 0; j < m.cols; j++) {
cout << m.data[i][j] << "\t";
}
cout << endl;
}
}
Matrix addMatrices(const Matrix& a, const Matrix& b) {
Matrix result(a.rows, a.cols);
for (int i = 0; i < a.rows; i++) {
for (int j = 0; j < a.cols; j++) {
result.data[i][j] = a.data[i][j] + b.data[i][j];
}
}
return result;
}
class Counter {
private:
int value;
public:
Counter(int v) : value(v) {}
Counter& increment() {
value++;
return *this;
}
Counter& add(int amount) {
value += amount;
return *this;
}
Counter& display() {
cout << "Value: " << value << endl;
return *this;
}
int getValue() const {
return value;
}
};
int main() {
cout << "=== Friend Function ===" << endl;
Matrix m1(2, 2);
m1.setValue(0, 0, 1).setValue(0, 1, 2).setValue(1, 0, 3).setValue(1, 1, 4);
printMatrix(m1);
Matrix m2(2, 2);
m2.setValue(0, 0, 5).setValue(0, 1, 6).setValue(1, 0, 7).setValue(1, 1, 8);
cout << "\n=== Friend Function: Add Matrices ===" << endl;
Matrix m3 = addMatrices(m1, m2);
printMatrix(m3);
cout << "\n=== Friend Class ===" << endl;
MatrixPrinter printer;
printer.print(m1);
cout << "\n=== this Pointer: Method Chaining ===" << endl;
Counter c(10);
c.increment().add(5).increment().display();
cout << "\n=== this Pointer: Return *this ===" << endl;
Counter c2(0);
c2.add(10).add(20).add(30).display();
return 0;
}
Code Explanation
-
friend void printMatrix(const Matrix& m)- A friend function. It is not a class member, but it can access the privaterows,cols, anddata. -
friend Matrix addMatrices(const Matrix& a, const Matrix& b)- A friend function that operates on two matrices at once. It accesses the private data of both objects. -
friend class MatrixPrinter- A friend class. All member functions of MatrixPrinter have access to Matrix's private members. -
MatrixPrinter printer; printer.print(m1);- Calls a MatrixPrinter member function that accesses Matrix's private data because of the friend class. -
Counter& increment() { value++; return *this; }- Uses thethispointer to return a reference to the object that called the function. -
c.increment().add(5).increment().display()- Method chaining. Because each function returns*this, the calls can be chained. -
thisimplicitly points to the object currently being executed. It is useful when a parameter and a data member have the same name. -
friendviolates encapsulation. Use it only when it is truly necessary, such as for operator overloading with streams.
Everyday Use Cases
Imagine a hospital. A patient (an object) has private medical data. But a specialist doctor (a friend) needs to access that data for treatment. The hospital (a friend class) also needs access for administration. The this pointer is like an ID card that always indicates "this is me" when someone talks about themselves.
Conclusion
A friend function gets access to a class's private and protected members. A friend class gives all member functions of the friend class full access. The this pointer points to the object currently being executed. Method chaining takes advantage of return *this so that function calls can be chained. Use friends wisely because they violate the principle of encapsulation.