Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Industrial programming >> Язык C

Дружественные функции и классы в C++: мастерство контроля доступа

Дружественные функции и классы в C++: мастерство контроля доступа

Это руководство демонстрирует, как объявлять и использовать дружественные функции и классы в C++, с наглядными примерами.

Сокрытие данных — основа ООП, предотвращающая прямой доступ внешнего кода к private членам класса. Protected члены видны только производным классам и недоступны извне.

Рассмотрим пример:

class MyClass {
private:
    int member1;
};
int main() {
    MyClass obj;
    // Ошибка! Нельзя обратиться к private членам отсюда.
    obj.member1 = 5;
}

Несмотря на это ограничение, C++ предлагает механизм дружественных функций (friend functions), который может обходить обычное управление доступом и работать с private и protected данными класса.

Дружественный класс (friend class) — похожая концепция, позволяющая целому классу быть другом. Обе возможности — мощные инструменты при умелом использовании, улучшающие инкапсуляцию без потери гибкости.


Дружественная функция в C++

Дружественная функция может читать и модифицировать private и protected члены класса. Она объявляется с ключевым словом friend внутри определения класса.

class ClassName {
    // ...
    friend returnType functionName(arguments);
    // ...
}

Пример 1: Базовая дружественная функция

// C++ программа для демонстрации работы дружественной функции
#include <iostream>
using namespace std;

class Distance {
private:
    int meter;
    // Объявление дружественной функции
    friend int addFive(Distance);
public:
    Distance() : meter(0) {}
};

// Определение дружественной функции
int addFive(Distance d) {
    // Доступ к private членам из дружественной функции
    d.meter += 5;
    return d.meter;
}

int main() {
    Distance D;
    cout << "Distance: " << addFive(D);
    return 0;
}

Вывод

Distance: 5

Функция addFive() показывает, что дружественная функция может свободно обращаться к private полю meter. Хотя пример простой, он иллюстрирует суть дружественных функций.


Пример 2: Работа с двумя классами

// Сложение членов двух разных классов с помощью дружественных функций
#include <iostream>
using namespace std;

// Прямое объявление (forward declaration)
class ClassB;

class ClassA {
public:
    // Конструктор, инициализирующий numA значением 12
    ClassA() : numA(12) {}
private:
    int numA;
    // Объявление дружественной функции
    friend int add(ClassA, ClassB);
};

class ClassB {
public:
    // Конструктор, инициализирующий numB значением 1
    ClassB() : numB(1) {}
private:
    int numB;
    // Объявление дружественной функции
    friend int add(ClassA, ClassB);
};

// Доступ к членам обоих классов
int add(ClassA objectA, ClassB objectB) {
    return (objectA.numA + objectB.numB);
}

int main() {
    ClassA objectA;
    ClassB objectB;
    cout << "Sum: " << add(objectA, objectB);
    return 0;
}

Вывод

Sum: 13

В этой программе оба класса ClassA и ClassB объявляют функцию add() как дружественную. Это даёт функции доступ к private данным обоих классов, позволяя сложить numA и numB.

Обратите внимание: объявление друга в ClassA ссылается на ClassB до её определения. Прямое объявление class ClassB; разрешает эту зависимость.


Дружественный класс в C++

Объявление целого класса другом даёт всем его функциям-членам доступ к private и protected членам хозяина. Синтаксис прост:

class ClassB;
class ClassA {
    // ClassB — дружественный класс ClassA
    friend class ClassB;
    // ...
}
class ClassB {
    // ...
}

Поскольку ClassB друг ClassA, любой метод внутри ClassB может свободно читать или модифицировать private данные ClassA. Обратное неверно: ClassA не может обратиться к private членам ClassB, если не объявит его другом.


Пример 3: Дружественный класс в действии

// C++ программа для демонстрации работы дружественного класса
#include <iostream>
using namespace std;

// Прямое объявление
class ClassB;

class ClassA {
private:
    int numA;
    // Объявление дружественного класса
    friend class ClassB;
public:
    // Конструктор, инициализирующий numA значением 12
    ClassA() : numA(12) {}
};

class ClassB {
private:
    int numB;
public:
    // Конструктор, инициализирующий numB значением 1
    ClassB() : numB(1) {}
    // Функция-член для сложения numA из ClassA и numB из ClassB
    int add() {
        ClassA objectA;
        return objectA.numA + numB;
    }
};

int main() {
    ClassB objectB;
    cout << "Sum: " << objectB.add();
    return 0;
}

Вывод

Sum: 13

Метод add() в ClassB может обратиться к private члену numA класса ClassA, потому что ClassA объявил ClassB другом. Этот пример показывает, как дружественные классы обеспечивают тесное сотрудничество с сохранением инкапсуляции.

В целом, дружественные функции и классы — ценные инструменты в C++, когда нужен контролируемый доступ через границы классов. Используйте их умеренно и только когда дизайн выигрывает от таких исключений из обычных правил доступа.

Резюме: когда использовать friend

Внимание: Чрезмерное использование friend нарушает инкапсуляцию и повышает связанность. Предпочитайте публичные интерфейсы, геттеры/сеттеры или переработку дизайна.

Язык C

  1. Классы и объекты в C#: Фундаменты надёжного ООП
  2. Абстрактные классы и методы в C#: практическое руководство
  3. Частичные классы и методы в C#: понимание и применение
  4. Sealed-классы и sealed-методы в C#: когда использовать, примеры и повышение безопасности кода
  5. Классы и объекты в C++: практическое руководство по объектно-ориентированному программированию
  6. C++ Struct vs Class: ключевые отличия, синтаксис и лучшие сценарии использования
  7. Java: объекты, классы и основные концепции ООП
  8. Классы хранения в C++: область видимости, время жизни и использование
  9. Полное руководство по дате и времени в C++
  10. Перегрузка в C++: функции и операторы — подробное руководство