моя контактная информация
Почтамезофия@protonmail.com
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Оглавление
Процессно-ориентированный и объектно-ориентированный
Объектно-ориентированного программирования
2. Квалификаторы доступа к классам и инкапсуляция
концепция создания экземпляров
Характеристики этого указателя
Процессно-ориентированное программирование — это идея программирования, ориентированная на процессы. В процессно-ориентированном программировании программа рассматривается как набор функций или процедур, которые выполняются в определенном порядке для выполнения конкретной задачи.
преимущество:
- Эффективная производительность : поскольку процессно-ориентированное программирование напрямую выполняет задачи в соответствии с процессом и не требует чрезмерного создания и управления объектами, оно имеет более высокую эффективность выполнения в некоторых сценариях с более высокими требованиями к производительности, таких как базовое системное программирование, встроенное программирование и т. д. Например, в ядре операционной системы можно использовать процессно-ориентированное программирование для лучшей оптимизации производительности при реализации таких функций, как планирование процессов и управление памятью.
- ясная логика : Для простой логики программы она реализуется шаг за шагом в соответствии с процессом. Логическая структура кода ясна и проста для понимания, проста в понимании и сопровождении. Например, простая программа, вычисляющая сумму двух чисел, может напрямую определить функцию для вычисления, используя процессно-ориентированное программирование.
недостаток:
- Плохая ремонтопригодность : Когда размер программы увеличивается, а функции становятся сложными, код, ориентированный на процедурное программирование, может стать трудным для поддержки и расширения. Поскольку связь между различными функциями высока, изменение одной функции может повлиять на другие связанные функции.
- Низкая возможность повторного использования кода: Повторное использование кода обычно достигается посредством вызовов функций, но для сложных функциональных модулей повторное использование сложнее, и функции не могут быть хорошо инкапсулированы и абстрагированы.
Объектно-ориентированное программирование — это идея объектно-центрированного программирования. Объекты — это сущности, которые содержат данные (свойства) и методы (поведения), которые работают с этими данными. Путем инкапсуляции связанных данных и методов в объект достигается интеграция данных и операций.
преимущество:
- Высокая ремонтопригодность : инкапсулировать функции в объекты, скрывая внутреннюю реализацию объектов от внешнего мира и уменьшая связь между модулями. Когда функцию необходимо изменить, необходимо изменить только внутреннюю реализацию соответствующего объекта, не затрагивая другие несвязанные части. Например, в приложении с графическим интерфейсом, если вы хотите изменить функцию кнопки, вам нужно только изменить соответствующий метод объекта кнопки, не затрагивая другие элементы интерфейса.
- Надежная возможность повторного использования кода : Повторного использования и расширения кода можно легко достичь с помощью наследования, полиморфизма и других функций.Например, создайте базовый класс
Shape
(форма), а затем вывестиCircle
(круглый),Rectangle
(Прямоугольник) и другие подклассы, подклассы могут повторно использовать атрибуты и методы базового класса и создавать определенные расширения.- Хорошая гибкость: Объектно-ориентированное программирование поддерживает полиморфизм, который позволяет программе динамически выбирать и выполнять соответствующие методы в соответствии с фактическим типом объекта во время выполнения, повышая гибкость и масштабируемость программы.
недостаток:
- Накладные расходы на производительность: поскольку создание объекта, вызов метода и другие операции требуют определенного объема накладных расходов, в некоторых сценариях с чрезвычайно высокими требованиями к производительности это может повлиять на эффективность выполнения программы.
- Высокая стоимость обучения: Концепции и особенности объектно-ориентированного программирования относительно сложны, что затрудняет их изучение и понимание новичками.
• class — это ключевое слово, определяющее класс, Data — это имя класса, а {} — тело класса. Обратите внимание, что завершающую точку с запятой нельзя опускать в конце определения класса. Содержимое тела класса называется членами класса: переменные в классе называются атрибутами, а переменные-члены класса называются методами или функциями-членами класса;
• Чтобы различать переменные-члены, обычно к переменной-члену принято добавлять специальный идентификатор, например начинаться с _ или m до или после переменной-члена. Обратите внимание, что это не является обязательным в C++, это всего лишь некоторые соглашения. .
• В C++ структура также может определять классы. C++ совместим с использованием структуры в C. В то же время структура была повышена до класса. Обычно в структуре можно определять функции. рекомендуется использовать class для определения классов.
• Функции-члены, определенные в классе, по умолчанию являются встроенными.
class Date { public: void Init(int year, int month, int day) { _year = year; _month = month; _day = day; } private: // 为了区分成员变量,⼀般习惯上成员变量 // 会加⼀个特殊标识,如_ 或者 m开头 int _year; // year_ m_year int _month; int _day; }; int main() { Date d; d.Init(2024, 3, 31); return 0; }
• Класс определяет новую область действия. Все члены класса находятся в области действия класса. При определении членов вне класса необходимо использовать оператор ::scope, чтобы указать, к какому домену класса принадлежит элемент.
• Домен класса влияет на правила поиска компиляции. Если Init в следующей программе не указывает стек домена класса, компилятор будет рассматривать Init как глобальную функцию. Тогда во время компиляции объявление/определение таких элементов, как массив, не может быть выполнено. найдено, будет сообщено об ошибке. Указание домена класса Stack означает знание того, что Init является функцией-членом. Если такие члены, как массив, не могут быть найдены в текущем домене, они будут искаться в домене класса.
- #include<iostream>
- using namespace std;
- class Stack
- {
- public:
- // 成员函数
- void Init(int n = 4);
- private:
- // 成员变量
- int* array;
- size_t capacity;
- size_t top;
- };
- // 声明和定义分离,需要指定类域
- void Stack::Init(int n)
- {
- array = (int*)malloc(sizeof(int) * n);
- if (nullptr == array)
- {
- perror("malloc申请空间失败");
- return;
- }
- capacity = n;
- top = 0;
- }
- int main()
- {
- Stack st;
- st.Init();
- return 0;
- }
• C++ — это способ реализовать инкапсуляцию, используя классы для объединения свойств и методов объекта, чтобы сделать объект более полным, и выборочно предоставлять его интерфейсы внешним пользователям посредством разрешений доступа.
• К членам, измененным с помощью public, можно получить прямой доступ за пределами класса; к членам, измененным с помощью protected и Private, нельзя получить прямой доступ за пределами класса. Protected и Private — это одно и то же, и их различия будут отражены в главе о наследовании.
• Область разрешений доступа начинается с позиции, где появляется квалификатор доступа, до появления следующего квалификатора доступа. Если последующего квалификатора доступа нет, область заканчивается }, то есть классом.
• Если член определения класса не изменяется квалификатором доступа, по умолчанию он становится закрытым.
• структура по умолчанию публичная
• Как правило, переменные-члены будут ограничены частными/защищенными, а функции-члены, которые должны использоваться другими, будут общедоступными.
Три основные характеристики объектно-ориентированного подхода: инкапсуляция, наследование и полиморфизм.
На этапе классов и объектов мы в основном изучаем характеристики инкапсуляции классов. Так что же такое инкапсуляция?
Инкапсуляция: органично объединяйте данные и методы обработки данных, скрывайте свойства и детали реализации объекта и открывайте интерфейс только для взаимодействия с объектом.
Инкапсуляция — это, по сути, своего рода управление, которое упрощает пользователям использование классов. Например: для такого сложного устройства, как компьютер, пользователю предоставляются только клавиши включения и выключения, ввод с клавиатуры, монитор, разъем USB и т. д., что позволяет пользователю взаимодействовать с компьютером и выполнять повседневные задачи. Но на самом деле настоящая работа компьютера — это процессор, видеокарта, память и другие аппаратные компоненты.
Пользователям компьютеров не нужно беспокоиться о внутренних основных компонентах, например о том, как расположены схемы на материнской плате, как устроен процессор и т. д. Пользователям нужно только знать, как включить компьютер и как его использовать. взаимодействовать с компьютером посредством клавиатуры и мыши. Поэтому, когда производители компьютеров покидают завод, они помещают оболочку снаружи, чтобы скрыть детали внутренней реализации, и размещают снаружи только выключатели питания, разъемы для мыши и клавиатуры, чтобы пользователи могли взаимодействовать с компьютером.
Для реализации инкапсуляции в языке C++ данные и методы для работы с данными могут быть органично объединены через классы, а права доступа могут использоваться для сокрытия внутренних деталей реализации объектов и контроля того, какие методы можно использовать непосредственно вне класса.
• Процесс создания объекта в физической памяти с использованием типа класса называется созданием экземпляра класса.
• Класс — это абстрактное описание объекта. Это что-то вроде модели, которая ограничивает переменные-члены класса. Эти переменные-члены только объявляются и не выделяют пространство при создании экземпляра объекта. сорт.
• Класс может создавать экземпляры нескольких объектов. Созданные экземпляры занимают фактическое физическое пространство и хранят переменные-члены класса. Например: создание экземпляров объектов из класса похоже на использование чертежей архитектурного проекта для строительства дома в реальности. не является физическим объектом. Даже если здание существует, оно не может жить в людях. Только когда дом построен по проектным чертежам, в нем можно жить. Тот же класс подобен проектному чертежу и не может хранить данные. Экземплярный объект выделяет физическую память для хранения данных.
Проанализируйте, какие члены входят в объект класса? Каждый объект, экземпляр которого создается классом, имеет независимое пространство данных, поэтому объект должен содержать переменные-члены. Итак, включены ли функции-члены? Во-первых, после компиляции функции это часть инструкций, которую нельзя сохранить в объекте. Эти инструкции хранятся в отдельной области (сегменте кода), поэтому, если их необходимо сохранить в объекте, их можно только сохранить. указатели на функции-члены. Давайте еще раз проанализируем, необходимо ли хранить указатели в объекте? Date создает экземпляры двух объектов d1 и d2. И d1, и d2 имеют свои собственные независимые переменные-члены _year/_month/_day для хранения собственных данных, но функция-член Init/Print. указатели d1 и d2 одинаковы, поэтому хранить их в объектах бесполезно. Если вы используете Date для создания экземпляров 100 объектов, то указатель функции-члена будет сохранен 100 раз, что слишком расточительно. На самом деле указатель функции не нужно сохранять. Указатель функции — это адрес. Вызывающая функция компилируется в ассемблерную инструкцию [адрес вызова]. Фактически, компилятор должен найти адрес функции при компиляции и компоновке. , а не во время выполнения. Во время выполнения обнаруживается только динамический полиморфизм, и адреса функций необходимо сохранять.
Выше мы проанализировали, что в объектах хранятся только переменные-члены. В C++ предусмотрено, что объекты, созданные классами, также должны соответствовать правилам выравнивания памяти.
Правила выравнивания памяти
Правила выравнивания памяти точно такие же, как и в языке C.Справочная статья:Язык C для расчета выравнивания памяти
Первый член находится по адресу, смещенному на 0 от структуры.
• Другие переменные-члены должны быть сопоставлены с адресами, которые являются целыми числами, кратными определенному числу (номеру выравнивания).
• Примечание. Логарифм = меньшее из числа выравнивания компилятора по умолчанию и размера члена.
• Логарифм по умолчанию в VS равен 8.
• Общий размер структуры: целое число, кратное максимальному числу выравнивания (наибольшему из всех типов переменных и наименьшему параметру выравнивания по умолчанию).
• Если структура является вложенной и вложенная структура выровнена по целому числу, кратному ее собственному максимальному логарифму, общий размер структуры равен максимальному числу выравниваний из всех (включая выравнивание вложенной структуры) чисел).
Если переменной-члена нет, необходимо указать 1 байт, потому что, если не указан даже байт, как можно показать, что объект существовал? Таким образом, 1 байт здесь отведен исключительно для идентификации существования объекта.
В классе Date есть две функции-члена: Init и Print. В теле функции нет различий между различными объектами. Итак, когда d1 вызывает функции Init и Print, как функция узнает, должна ли она обращаться к объекту d1 или к ней. объект d2?Затем мы увидим, что C++ предоставляет неявный указатель this для решения данной проблемы.
• После компиляции компилятора функции-члены класса по умолчанию добавляют указатель текущего типа класса, называемый этим указателем, в первую позицию формального параметра. Например, реальный прототип класса Init of Date:void Init(Date* const this, intyear, intmonth, int day) • При доступе к переменным-членам в функциях-членах класса доступ к ним осуществляется, по существу, через этот указатель. Например, при присвоении значения _year в функции Init это. ->_год = год;
• В C++ предусмотрено, что этот указатель не может быть записан явно в позиции фактических параметров и формальных параметров (компилятор будет обрабатывать его во время компиляции), но этот указатель можно явно использовать в теле функции.
- #include<iostream>
- using namespace std;
- class Date
- {
- public:
- // void Init(Date* const this, int year, int month, int day)
- void Init(int year, int month, int day)
- {
- // 编译报错:error C2106: “=”: 左操作数必须为左值
- // this = nullptr;
- // this->_year = year;
- _year = year;
- this->_month = month;
- this->_day = day;
- }
- void Print()
- {
- cout << _year << "/" << _month << "/" << _day << endl;
- }
- private:
- // 这⾥只是声明,没有开空间
- int _year;
- int _month;
- int _day;
- };
- int main()
- {
- // Date类实例化出对象d1和d2
- Date d1;
- Date d2;
- d1.Init(2024, 7, 1); // d1.Init(&d1, 2024, 7, 1);
- d1.Print(); // d1.Print(&d1);
- d2.Init(2024, 7, 10); // d2.Init(&d2, 2024, 7, 10);
- d2.Print(); // d2.Print(&d2);
- return 0;
- }