Shiklo Tools
PDF40
Image20
Calculators & Converters25
Text & Writing13
Developer26
Video14
Audio14
Document14
Data & Spreadsheet12
Web & SEO9
OCR & Scanning5
Archive & File12
Security & Privacy23
Health & Medical29
QR & Barcode5

C++ Friend Functions and static Members

Normally every object has its own copy of the class's data. static members belong to the class itself and are shared by all its objects. friend functions are functions outside the class that the class allows to see its private members.

static data members

A static member exists once, no matter how many objects there are. A common use is counting objects. Since C++17, inline static lets you give it a value inside the class.

#include <iostream>
#include <string>

class Player {
    std::string name;
    inline static int count = 0;     // shared by all players
public:
    explicit Player(const std::string& n) : name(n) { count++; }
    ~Player() { count--; }
    static int howMany() { return count; }
};

int main() {
    Player a("Asha");
    Player b("Ravi");
    std::cout << Player::howMany() << " players\n";
    {
        Player c("Kiran");
        std::cout << Player::howMany() << " players\n";
    }
    std::cout << Player::howMany() << " players\n";
    return 0;
}
Output
2 players
3 players
2 players

static methods

A static method belongs to the class, not to an object, so it is called with the class name: Player::howMany(). It cannot use the non-static members, because there is no object (this) for it. Static methods are also used for helper functions that belong with the class, such as Date::isLeapYear(2024).

friend functions

A class can name a function as its friend. The friend is not a member, but it may use the private members. The most common friend is operator<<, which lets cout print the object (see Operator Overloading):

#include <iostream>

class Fraction {
    int num, den;
public:
    Fraction(int n, int d) : num(n), den(d) {}
    friend std::ostream& operator<<(std::ostream& os, const Fraction& f);
    friend Fraction multiply(const Fraction& a, const Fraction& b);
};

std::ostream& operator<<(std::ostream& os, const Fraction& f) {
    return os << f.num << "/" << f.den;      // may read private members
}

Fraction multiply(const Fraction& a, const Fraction& b) {
    return Fraction(a.num * b.num, a.den * b.den);
}

int main() {
    Fraction half(1, 2), third(1, 3);
    std::cout << half << " * " << third << " = " << multiply(half, third) << "\n";
    return 0;
}
Output
1/2 * 1/3 = 1/6

Use friends sparingly

Every friend weakens encapsulation a little, because it can change the private data. Use friends for operators and for closely related helper functions; for everything else, prefer public methods.

Practice exercises

  1. Give a BankAccount class a static interest rate shared by all accounts and a static method to change it.
  2. Add a static method Date::isLeapYear(int year) and call it without creating a Date.
  3. Write a friend function add for Fraction and print the sum of 1/2 and 1/3 (the result does not have to be reduced).