C++98corebeginner
Friend Functions
C++98 · The Foundation · Compiler flag: -std=c++98
Explanation
Non-member functions granted access to a class’s private members.
Real-World Scenario
Allow a logging function to access private data in a debug system.
Quick Snippet
snippet.cpp
class Data { friend void log(Data&); };Full Example
friend_functions.cpp
// CodeNebula - C++98 Example: Friend Functions
// Compile: g++ -std=c++98 -Wall -Wextra -o example friend_functions.cpp
//
// This example demonstrates:
// - Declaring a non-member function as a friend of a class
// - Friend functions can access private and protected members
// - Common use case: operator overloading (operator<<, operator+)
// - Friend functions are NOT member functions (no 'this' pointer)
// - Friendship is granted, not taken -- the class decides who its friends are
#include <iostream>
#include <cmath>
// ============================================================
// 1. Basic friend function
// ============================================================
class SecretBox {
private:
int secretNumber;
char secretWord[32];
public:
SecretBox(int num, const char* word) : secretNumber(num) {
std::strncpy(secretWord, word, 31);
secretWord[31] = '\0';
}
// Declare reveal() as a friend -- it can access private members
friend void reveal(const SecretBox& box);
};
// Definition of the friend function (NOT a member function)
void reveal(const SecretBox& box) {
std::cout << " Secret number: " << box.secretNumber << std::endl;
std::cout << " Secret word: " << box.secretWord << std::endl;
}
// ============================================================
// 2. Friend function for operator overloading
// ============================================================
class Vector2D {
private:
double x, y;
public:
Vector2D(double xv, double yv) : x(xv), y(yv) {}
double getX() const { return x; }
double getY() const { return y; }
double magnitude() const { return std::sqrt(x * x + y * y); }
// Member operator+
Vector2D operator+(const Vector2D& rhs) const {
return Vector2D(x + rhs.x, y + rhs.y);
}
// Friend: operator<< (cannot be a member -- left operand is ostream)
friend std::ostream& operator<<(std::ostream& os, const Vector2D& v);
// Friend: operator* for scalar * Vector2D (scalar on the LEFT)
// Cannot be a member of Vector2D because the left operand is a double
friend Vector2D operator*(double scalar, const Vector2D& v);
// Friend: distance function that needs private access to both vectors
friend double distance(const Vector2D& a, const Vector2D& b);
};
std::ostream& operator<<(std::ostream& os, const Vector2D& v) {
os << "(" << v.x << ", " << v.y << ")"; // accesses private x, y
return os;
}
Vector2D operator*(double scalar, const Vector2D& v) {
return Vector2D(scalar * v.x, scalar * v.y); // accesses private x, y
}
double distance(const Vector2D& a, const Vector2D& b) {
double dx = a.x - b.x; // accesses private members of both objects
double dy = a.y - b.y;
return std::sqrt(dx * dx + dy * dy);
}
// ============================================================
// 3. Friend function operating on two different classes
// ============================================================
class Celsius; // forward declaration
class Fahrenheit {
private:
double temp;
public:
Fahrenheit(double t) : temp(t) {}
friend void compare(const Celsius& c, const Fahrenheit& f);
friend std::ostream& operator<<(std::ostream& os, const Fahrenheit& f) {
os << f.temp << " F";
return os;
}
};
class Celsius {
private:
double temp;
public:
Celsius(double t) : temp(t) {}
friend void compare(const Celsius& c, const Fahrenheit& f);
friend std::ostream& operator<<(std::ostream& os, const Celsius& c) {
os << c.temp << " C";
return os;
}
};
// This function is a friend of BOTH classes
void compare(const Celsius& c, const Fahrenheit& f) {
double cInF = c.temp * 9.0 / 5.0 + 32.0;
std::cout << " " << c << " = " << cInF << " F" << std::endl;
std::cout << " " << f << std::endl;
if (cInF > f.temp) {
std::cout << " Celsius value is higher" << std::endl;
} else if (cInF < f.temp) {
std::cout << " Fahrenheit value is higher" << std::endl;
} else {
std::cout << " They are equal" << std::endl;
}
}
int main() {
std::cout << "========================================" << std::endl;
std::cout << "1. BASIC FRIEND FUNCTION" << std::endl;
std::cout << "========================================" << std::endl;
{
SecretBox box(42, "OpenSesame");
// box.secretNumber; // COMPILE ERROR: private
// But the friend function can access it:
reveal(box);
}
std::cout << "\n========================================" << std::endl;
std::cout << "2. FRIEND FOR OPERATOR OVERLOADING" << std::endl;
std::cout << "========================================" << std::endl;
{
Vector2D a(3.0, 4.0);
Vector2D b(1.0, 2.0);
// operator<< (friend)
std::cout << " a = " << a << std::endl;
std::cout << " b = " << b << std::endl;
// operator+ (member)
Vector2D c = a + b;
std::cout << " a + b = " << c << std::endl;
// scalar * Vector2D (friend -- scalar on left)
Vector2D d = 2.5 * a;
std::cout << " 2.5 * a = " << d << std::endl;
// distance (friend)
std::cout << " distance(a, b) = " << distance(a, b) << std::endl;
std::cout << " magnitude of a = " << a.magnitude() << std::endl;
}
std::cout << "\n========================================" << std::endl;
std::cout << "3. FRIEND OF TWO CLASSES" << std::endl;
std::cout << "========================================" << std::endl;
{
Celsius c(100.0);
Fahrenheit f(212.0);
compare(c, f);
std::cout << std::endl;
Celsius c2(0.0);
Fahrenheit f2(100.0);
compare(c2, f2);
}
std::cout << "\n========================================" << std::endl;
std::cout << "4. KEY POINTS ABOUT FRIEND FUNCTIONS" << std::endl;
std::cout << "========================================" << std::endl;
std::cout << " - Declared inside the class with 'friend' keyword" << std::endl;
std::cout << " - Defined OUTSIDE the class (not a member)" << std::endl;
std::cout << " - Has access to private and protected members" << std::endl;
std::cout << " - No 'this' pointer -- must receive objects as parameters" << std::endl;
std::cout << " - Friendship is NOT inherited, transitive, or reciprocal" << std::endl;
std::cout << " - Common use: operator<<, operator>>, binary operators" << std::endl;
std::cout << " where the left operand is not the class type" << std::endl;
return 0;
}
// Expected output:
// ========================================
// 1. BASIC FRIEND FUNCTION
// ========================================
// Secret number: 42
// Secret word: OpenSesame
//
// ========================================
// 2. FRIEND FOR OPERATOR OVERLOADING
// ========================================
// a = (3, 4)
// b = (1, 2)
// a + b = (4, 6)
// 2.5 * a = (7.5, 10)
// distance(a, b) = 2.82843
// magnitude of a = 5
//
// ========================================
// 3. FRIEND OF TWO CLASSES
// ========================================
// 100 C = 212 F
// 212 F
// They are equal
//
// 0 C = 32 F
// 100 F
// Fahrenheit value is higher
//
// ========================================
// 4. KEY POINTS ABOUT FRIEND FUNCTIONS
// ========================================
// ...summary...
Run command
g++ -std=c++98 -Wall -Wextra -o example friend_functions.cpp