Обмен технологиями

Классы и объекты C (1)

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Оглавление

Процессно-ориентированный и объектно-ориентированный

Процедурное программирование

Объектно-ориентированного программирования

1. Определение класса

Формат определения класса

домен класса

2. Квалификаторы доступа к классам и инкапсуляция

квалификатор доступа

инкапсуляция

3. Создание экземпляра

концепция создания экземпляров

размер объекта

4. этот указатель

Характеристики этого указателя


Процессно-ориентированный и объектно-ориентированный

  • Язык C — типичный процессно-ориентированный язык программирования. Разработка программы в основном вращается вокруг функций и структур данных, уделяя особое внимание процессу реализации функций.
  • C++ поддерживает как процедурное, так и объектно-ориентированное программирование. Основные концепции объектно-ориентированного программирования включают классы, объекты, инкапсуляцию, наследование, полиморфизм и т. д., которые делают организацию и дизайн программы более согласованными с реальной моделью и улучшают удобство сопровождения и масштабируемость кода.

Процедурное программирование

Процессно-ориентированное программирование — это идея программирования, ориентированная на процессы. В процессно-ориентированном программировании программа рассматривается как набор функций или процедур, которые выполняются в определенном порядке для выполнения конкретной задачи.

преимущество:

  • Эффективная производительность : поскольку процессно-ориентированное программирование напрямую выполняет задачи в соответствии с процессом и не требует чрезмерного создания и управления объектами, оно имеет более высокую эффективность выполнения в некоторых сценариях с более высокими требованиями к производительности, таких как базовое системное программирование, встроенное программирование и т. д. Например, в ядре операционной системы можно использовать процессно-ориентированное программирование для лучшей оптимизации производительности при реализации таких функций, как планирование процессов и управление памятью.
  • ясная логика : Для простой логики программы она реализуется шаг за шагом в соответствии с процессом. Логическая структура кода ясна и проста для понимания, проста в понимании и сопровождении. Например, простая программа, вычисляющая сумму двух чисел, может напрямую определить функцию для вычисления, используя процессно-ориентированное программирование.

недостаток:

  • Плохая ремонтопригодность : Когда размер программы увеличивается, а функции становятся сложными, код, ориентированный на процедурное программирование, может стать трудным для поддержки и расширения. Поскольку связь между различными функциями высока, изменение одной функции может повлиять на другие связанные функции.
  • Низкая возможность повторного использования кода: Повторное использование кода обычно достигается посредством вызовов функций, но для сложных функциональных модулей повторное использование сложнее, и функции не могут быть хорошо инкапсулированы и абстрагированы.

Объектно-ориентированного программирования

Объектно-ориентированное программирование — это идея объектно-центрированного программирования. Объекты — это сущности, которые содержат данные (свойства) и методы (поведения), которые работают с этими данными. Путем инкапсуляции связанных данных и методов в объект достигается интеграция данных и операций.

преимущество:

  • Высокая ремонтопригодность : инкапсулировать функции в объекты, скрывая внутреннюю реализацию объектов от внешнего мира и уменьшая связь между модулями. Когда функцию необходимо изменить, необходимо изменить только внутреннюю реализацию соответствующего объекта, не затрагивая другие несвязанные части. Например, в приложении с графическим интерфейсом, если вы хотите изменить функцию кнопки, вам нужно только изменить соответствующий метод объекта кнопки, не затрагивая другие элементы интерфейса.
  • Надежная возможность повторного использования кода : Повторного использования и расширения кода можно легко достичь с помощью наследования, полиморфизма и других функций.Например, создайте базовый классShape(форма), а затем вывестиCircle(круглый),Rectangle(Прямоугольник) и другие подклассы, подклассы могут повторно использовать атрибуты и методы базового класса и создавать определенные расширения.
  • Хорошая гибкость: Объектно-ориентированное программирование поддерживает полиморфизм, который позволяет программе динамически выбирать и выполнять соответствующие методы в соответствии с фактическим типом объекта во время выполнения, повышая гибкость и масштабируемость программы.

недостаток:

  • Накладные расходы на производительность: поскольку создание объекта, вызов метода и другие операции требуют определенного объема накладных расходов, в некоторых сценариях с чрезвычайно высокими требованиями к производительности это может повлиять на эффективность выполнения программы.
  • Высокая стоимость обучения: Концепции и особенности объектно-ориентированного программирования относительно сложны, что затрудняет их изучение и понимание новичками.

1. Определение класса

Формат определения класса

• class — это ключевое слово, определяющее класс, Data — это имя класса, а {} — тело класса. Обратите внимание, что завершающую точку с запятой нельзя опускать в конце определения класса. Содержимое тела класса называется членами класса: переменные в классе называются атрибутами, а переменные-члены класса называются методами или функциями-членами класса;

• Чтобы различать переменные-члены, обычно к переменной-члену принято добавлять специальный идентификатор, например начинаться с _ или m до или после переменной-члена. Обратите внимание, что это не является обязательным в C++, это всего лишь некоторые соглашения. .

• В C++ структура также может определять классы. C++ совместим с использованием структуры в C. В то же время структура была повышена до класса. Обычно в структуре можно определять функции. рекомендуется использовать class для определения классов.

• Функции-члены, определенные в классе, по умолчанию являются встроенными.

  1. class Date
  2. {
  3. public:
  4. void Init(int year, int month, int day)
  5. {
  6. _year = year;
  7. _month = month;
  8. _day = day;
  9. }
  10. private:
  11. // 为了区分成员变量,⼀般习惯上成员变量
  12. // 会加⼀个特殊标识,如_ 或者 m开头
  13. int _year; // year_ m_year
  14. int _month;
  15. int _day;
  16. };
  17. int main()
  18. {
  19. Date d;
  20. d.Init(2024, 3, 31);
  21. return 0;
  22. }

домен класса

• Класс определяет новую область действия. Все члены класса находятся в области действия класса. При определении членов вне класса необходимо использовать оператор ::scope, чтобы указать, к какому домену класса принадлежит элемент.

• Домен класса влияет на правила поиска компиляции. Если Init в следующей программе не указывает стек домена класса, компилятор будет рассматривать Init как глобальную функцию. Тогда во время компиляции объявление/определение таких элементов, как массив, не может быть выполнено. найдено, будет сообщено об ошибке. Указание домена класса Stack означает знание того, что Init является функцией-членом. Если такие члены, как массив, не могут быть найдены в текущем домене, они будут искаться в домене класса.

  1. #include<iostream>
  2. using namespace std;
  3. class Stack
  4. {
  5. public:
  6. // 成员函数
  7. void Init(int n = 4);
  8. private:
  9. // 成员变量
  10. int* array;
  11. size_t capacity;
  12. size_t top;
  13. };
  14. // 声明和定义分离,需要指定类域
  15. void Stack::Init(int n)
  16. {
  17. array = (int*)malloc(sizeof(int) * n);
  18. if (nullptr == array)
  19. {
  20. perror("malloc申请空间失败");
  21. return;
  22. }
  23. capacity = n;
  24. top = 0;
  25. }
  26. int main()
  27. {
  28. Stack st;
  29. st.Init();
  30. return 0;
  31. }

2. Квалификаторы доступа к классам и инкапсуляция

квалификатор доступа

• C++ — это способ реализовать инкапсуляцию, используя классы для объединения свойств и методов объекта, чтобы сделать объект более полным, и выборочно предоставлять его интерфейсы внешним пользователям посредством разрешений доступа.

• К членам, измененным с помощью public, можно получить прямой доступ за пределами класса; к членам, измененным с помощью protected и Private, нельзя получить прямой доступ за пределами класса. Protected и Private — это одно и то же, и их различия будут отражены в главе о наследовании.

• Область разрешений доступа начинается с позиции, где появляется квалификатор доступа, до появления следующего квалификатора доступа. Если последующего квалификатора доступа нет, область заканчивается }, то есть классом.

• Если член определения класса не изменяется квалификатором доступа, по умолчанию он становится закрытым.

• структура по умолчанию публичная

• Как правило, переменные-члены будут ограничены частными/защищенными, а функции-члены, которые должны использоваться другими, будут общедоступными.

инкапсуляция

Три основные характеристики объектно-ориентированного подхода: инкапсуляция, наследование и полиморфизм.

На этапе классов и объектов мы в основном изучаем характеристики инкапсуляции классов. Так что же такое инкапсуляция?

Инкапсуляция: органично объединяйте данные и методы обработки данных, скрывайте свойства и детали реализации объекта и открывайте интерфейс только для взаимодействия с объектом.

Инкапсуляция — это, по сути, своего рода управление, которое упрощает пользователям использование классов. Например: для такого сложного устройства, как компьютер, пользователю предоставляются только клавиши включения и выключения, ввод с клавиатуры, монитор, разъем USB и т. д., что позволяет пользователю взаимодействовать с компьютером и выполнять повседневные задачи. Но на самом деле настоящая работа компьютера — это процессор, видеокарта, память и другие аппаратные компоненты.

Пользователям компьютеров не нужно беспокоиться о внутренних основных компонентах, например о том, как расположены схемы на материнской плате, как устроен процессор и т. д. Пользователям нужно только знать, как включить компьютер и как его использовать. взаимодействовать с компьютером посредством клавиатуры и мыши. Поэтому, когда производители компьютеров покидают завод, они помещают оболочку снаружи, чтобы скрыть детали внутренней реализации, и размещают снаружи только выключатели питания, разъемы для мыши и клавиатуры, чтобы пользователи могли взаимодействовать с компьютером.

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

3. Создание экземпляра

концепция создания экземпляров

• Процесс создания объекта в физической памяти с использованием типа класса называется созданием экземпляра класса.

• Класс — это абстрактное описание объекта. Это что-то вроде модели, которая ограничивает переменные-члены класса. Эти переменные-члены только объявляются и не выделяют пространство при создании экземпляра объекта. сорт.

• Класс может создавать экземпляры нескольких объектов. Созданные экземпляры занимают фактическое физическое пространство и хранят переменные-члены класса. Например: создание экземпляров объектов из класса похоже на использование чертежей архитектурного проекта для строительства дома в реальности. не является физическим объектом. Даже если здание существует, оно не может жить в людях. Только когда дом построен по проектным чертежам, в нем можно жить. Тот же класс подобен проектному чертежу и не может хранить данные. Экземплярный объект выделяет физическую память для хранения данных.

размер объекта

Проанализируйте, какие члены входят в объект класса? Каждый объект, экземпляр которого создается классом, имеет независимое пространство данных, поэтому объект должен содержать переменные-члены. Итак, включены ли функции-члены? Во-первых, после компиляции функции это часть инструкций, которую нельзя сохранить в объекте. Эти инструкции хранятся в отдельной области (сегменте кода), поэтому, если их необходимо сохранить в объекте, их можно только сохранить. указатели на функции-члены. Давайте еще раз проанализируем, необходимо ли хранить указатели в объекте? Date создает экземпляры двух объектов d1 и d2. И d1, и d2 имеют свои собственные независимые переменные-члены _year/_month/_day для хранения собственных данных, но функция-член Init/Print. указатели d1 и d2 одинаковы, поэтому хранить их в объектах бесполезно. Если вы используете Date для создания экземпляров 100 объектов, то указатель функции-члена будет сохранен 100 раз, что слишком расточительно. На самом деле указатель функции не нужно сохранять. Указатель функции — это адрес. Вызывающая функция компилируется в ассемблерную инструкцию [адрес вызова]. Фактически, компилятор должен найти адрес функции при компиляции и компоновке. , а не во время выполнения. Во время выполнения обнаруживается только динамический полиморфизм, и адреса функций необходимо сохранять.

Выше мы проанализировали, что в объектах хранятся только переменные-члены. В C++ предусмотрено, что объекты, созданные классами, также должны соответствовать правилам выравнивания памяти.

Правила выравнивания памяти

Правила выравнивания памяти точно такие же, как и в языке C.Справочная статья:Язык C для расчета выравнивания памяти

Первый член находится по адресу, смещенному на 0 от структуры.

• Другие переменные-члены должны быть сопоставлены с адресами, которые являются целыми числами, кратными определенному числу (номеру выравнивания).

• Примечание. Логарифм = меньшее из числа выравнивания компилятора по умолчанию и размера члена.

• Логарифм по умолчанию в VS равен 8.

• Общий размер структуры: целое число, кратное максимальному числу выравнивания (наибольшему из всех типов переменных и наименьшему параметру выравнивания по умолчанию).

• Если структура является вложенной и вложенная структура выровнена по целому числу, кратному ее собственному максимальному логарифму, общий размер структуры равен максимальному числу выравниваний из всех (включая выравнивание вложенной структуры) чисел).

Если переменной-члена нет, необходимо указать 1 байт, потому что, если не указан даже байт, как можно показать, что объект существовал? Таким образом, 1 байт здесь отведен исключительно для идентификации существования объекта.

4. этот указатель

Характеристики этого указателя

В классе Date есть две функции-члена: Init и Print. В теле функции нет различий между различными объектами. Итак, когда d1 вызывает функции Init и Print, как функция узнает, должна ли она обращаться к объекту d1 или к ней. объект d2?Затем мы увидим, что C++ предоставляет неявный указатель this для решения данной проблемы.

• После компиляции компилятора функции-члены класса по умолчанию добавляют указатель текущего типа класса, называемый этим указателем, в первую позицию формального параметра. Например, реальный прототип класса Init of Date:void Init(Date* const this, intyear, intmonth, int day) • При доступе к переменным-членам в функциях-членах класса доступ к ним осуществляется, по существу, через этот указатель. Например, при присвоении значения _year в функции Init это. -&gt;_год = год;

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

  1. #include<iostream>
  2. using namespace std;
  3. class Date
  4. {
  5. public:
  6. // void Init(Date* const this, int year, int month, int day)
  7. void Init(int year, int month, int day)
  8. {
  9. // 编译报错:error C2106: “=”: 左操作数必须为左值
  10. // this = nullptr;
  11. // this->_year = year;
  12. _year = year;
  13. this->_month = month;
  14. this->_day = day;
  15. }
  16. void Print()
  17. {
  18. cout << _year << "/" << _month << "/" << _day << endl;
  19. }
  20. private:
  21. // 这⾥只是声明,没有开空间
  22. int _year;
  23. int _month;
  24. int _day;
  25. };
  26. int main()
  27. {
  28. // Date类实例化出对象d1和d2
  29. Date d1;
  30. Date d2;
  31. d1.Init(2024, 7, 1); // d1.Init(&d1, 2024, 7, 1);
  32. d1.Print(); // d1.Print(&d1);
  33. d2.Init(2024, 7, 10); // d2.Init(&d2, 2024, 7, 10);
  34. d2.Print(); // d2.Print(&d2);
  35. return 0;
  36. }