내 연락처 정보
우편메소피아@프로톤메일.com
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
목차
프로세스 지향 프로그래밍은 프로세스 중심 프로그래밍 아이디어입니다. 프로세스 지향 프로그래밍에서 프로그램은 특정 작업을 완료하기 위해 특정 순서로 실행되는 함수 또는 프로시저의 모음으로 간주됩니다.
이점:
- 효율적인 성능 : 프로세스 지향 프로그래밍은 프로세스에 따라 작업을 직접 실행하고 과도한 객체 생성 및 관리가 필요하지 않기 때문에 기본 시스템 프로그래밍, 임베디드 프로그래밍 등과 같이 성능 요구 사항이 더 높은 일부 시나리오에서 실행 효율성이 더 높습니다. 예를 들어, 운영 체제 커널에서는 프로세스 지향 프로그래밍을 사용하여 프로세스 스케줄링 및 메모리 관리와 같은 기능 구현을 위한 성능을 더 효과적으로 최적화할 수 있습니다.
- 명확한 논리 : 간단한 프로그램 로직을 위해 프로세스에 따라 단계별로 구현합니다. 코드의 논리적 구조가 명확하고 이해하기 쉽고 유지 관리가 쉽습니다. 예를 들어, 두 숫자의 합을 계산하는 간단한 프로그램은 프로세스 지향 프로그래밍을 사용하여 계산을 위한 함수를 직접 정의할 수 있습니다.
결점:
- 유지 관리성이 좋지 않음 : 프로그램 크기가 커지고 기능이 복잡해지면 절차적 프로그래밍 중심의 코드는 유지 관리 및 확장이 어려워질 수 있습니다. 다양한 기능 간의 결합도가 높기 때문에 하나의 기능을 수정하면 관련된 다른 기능에 영향을 미칠 수 있습니다.
- 낮은 코드 재사용성: 코드 재사용은 일반적으로 함수 호출을 통해 이루어지지만 복잡한 기능 모듈의 경우 재사용이 더 어렵고 함수를 잘 캡슐화하고 추상화할 수 없습니다.
객체 지향 프로그래밍은 객체 중심 프로그래밍 아이디어입니다. 객체는 데이터(속성)와 해당 데이터에 대해 작동하는 메서드(동작)를 포함하는 엔터티입니다. 관련 데이터와 메소드를 객체에 캡슐화함으로써 데이터와 작업의 통합이 달성됩니다.
이점:
- 높은 유지보수성 : 객체에 함수를 캡슐화하고 객체의 내부 구현을 외부 세계로부터 숨기고 모듈 간의 결합을 줄입니다. 함수를 수정해야 하는 경우에는 관련 없는 다른 부분에 영향을 주지 않고 해당 객체의 내부 구현만 수정하면 됩니다. 예를 들어, 그래픽 인터페이스 애플리케이션에서 버튼의 기능을 수정하려면 다른 인터페이스 요소에 영향을 주지 않고 버튼 개체의 해당 메서드만 수정하면 됩니다.
- 강력한 코드 재사용성 : 상속, 다형성 및 기타 기능을 통해 코드 재사용 및 확장이 쉽게 이루어질 수 있습니다.예를 들어 기본 클래스를 만듭니다.
Shape
(모양)을 도출한 다음Circle
(둥근),Rectangle
(Rectangle) 및 기타 하위 클래스인 하위 클래스는 기본 클래스의 특성과 메서드를 재사용하고 특정 확장을 만들 수 있습니다.- 좋은 유연성: 객체지향 프로그래밍은 다형성을 지원합니다. 이는 프로그램이 런타임 중에 객체의 실제 유형에 따라 해당 메소드를 동적으로 선택하고 실행할 수 있도록 하여 프로그램의 유연성과 확장성을 높입니다.
결점:
- 성능 오버헤드: 개체 생성, 메서드 호출 및 기타 작업에는 일정량의 오버헤드가 필요하므로 성능 요구 사항이 매우 높은 일부 시나리오에서는 프로그램의 실행 효율성에 영향을 미칠 수 있습니다.
- 높은 학습 비용: 객체지향 프로그래밍의 개념과 특징은 상대적으로 복잡하여 초보자가 배우고 이해하기가 어렵습니다.
• class는 클래스를 정의하는 키워드이고, Data는 클래스의 이름이며, {}는 클래스의 본문입니다. 클래스 정의 끝에는 후행 세미콜론이 생략될 수 없습니다. 클래스 본문에 있는 내용을 클래스의 멤버라고 합니다. 클래스에 있는 변수를 클래스의 속성 또는 멤버 변수라고 합니다. 클래스에 있는 함수를 클래스의 메서드 또는 멤버 함수라고 합니다.
• 멤버 변수를 구별하기 위해 일반적으로 멤버 변수 앞이나 뒤에 _ 또는 m으로 시작하는 등의 특수 식별자를 멤버 변수에 추가하는 것이 관례입니다. 이는 C++에서는 필수 사항이 아니며 단지 일부 관례일 뿐입니다. .
• C++에서 struct는 클래스를 정의할 수도 있습니다. C++는 C의 struct 사용법과 호환됩니다. 동시에 struct는 클래스로 업그레이드되었습니다. 일반적으로 struct에서 함수를 정의할 수 있습니다. 클래스를 정의하려면 클래스를 사용하는 것이 좋습니다.
• 클래스에 정의된 멤버 함수는 기본적으로 인라인입니다.
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가 클래스 도메인 Stack을 지정하지 않으면 컴파일러는 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으로 수정한 멤버는 클래스 외부에서 직접 접근할 수 없으며 차이점은 나중에 상속 장에서 반영됩니다.
• 접근권한의 범위는 접근한정자가 나타나는 위치부터 다음 접근한정자가 나타날 때까지이다. 만약 후속 접근한정자가 없다면 그 범위는 }, 즉 클래스에서 끝난다.
• 클래스 정의 멤버가 액세스 한정자에 의해 수정되지 않으면 기본값은 private입니다.
• 구조체의 기본값은 공개입니다.
• 일반적으로 멤버변수는 private/protected로 제한하고, 다른 사람이 사용해야 하는 멤버함수는 public으로 설정한다.
객체지향의 세 가지 주요 특징은 캡슐화, 상속, 다형성입니다.
클래스와 객체 단계에서는 주로 클래스의 캡슐화 특성을 연구합니다. 그러면 캡슐화란 무엇일까요?
캡슐화(Encapsulation): 데이터와 데이터를 조작하는 방법을 유기적으로 결합하고, 객체의 속성과 구현 세부 사항을 숨기고, 객체와 상호 작용할 수 있는 인터페이스만 노출합니다.
캡슐화는 본질적으로 사용자가 클래스를 더 쉽게 사용할 수 있도록 하는 일종의 관리입니다. 예: 컴퓨터와 같은 복잡한 장치의 경우 사용자에게 제공되는 유일한 것은 전원 켜기 및 끄기 키, 키보드 입력, 모니터, USB 잭 등으로 사용자가 컴퓨터와 상호 작용하고 일상 작업을 완료할 수 있도록 해줍니다. 그러나 실제로 컴퓨터의 실제 작업은 CPU, 그래픽 카드, 메모리 및 기타 하드웨어 구성 요소입니다.
컴퓨터 사용자의 경우 마더보드의 회로 배치, CPU 설계 등 내부 핵심 구성 요소에 대해 걱정할 필요가 없습니다. 사용자는 컴퓨터를 켜는 방법과 작동하는 방법만 알면 됩니다. 키보드와 마우스를 통해 컴퓨터와 상호 작용합니다. 따라서 컴퓨터 제조업체는 공장을 떠날 때 내부 구현 세부 사항을 숨기기 위해 외부에 쉘을 배치하고 사용자가 컴퓨터와 상호 작용할 수 있도록 전원 스위치, 마우스 및 키보드 잭만 외부에 제공합니다.
C++ 언어로 캡슐화를 구현하기 위해서는 데이터를 연산하는 데이터와 메소드를 클래스를 통해 유기적으로 결합할 수 있고, 접근 권한을 이용해 객체의 내부 구현 내용을 숨기고 클래스 외부에서 직접 어떤 메소드를 사용할 수 있는지 제어할 수 있다.
• 클래스 유형을 사용하여 물리적 메모리에 객체를 생성하는 프로세스를 클래스 인스턴스화라고 합니다.
• 클래스는 객체에 대한 추상적인 설명으로, 클래스의 멤버 변수를 제한합니다. 이러한 멤버 변수는 객체가 인스턴스화될 때 공간을 할당하지 않습니다. 수업.
• 클래스는 여러 객체를 인스턴스화할 수 있으며, 인스턴스화된 객체는 실제 물리적 공간을 차지하고 클래스 멤버 변수를 저장합니다. 예를 들어, 클래스에서 객체를 인스턴스화하는 것은 건축 설계 도면을 사용하여 실제로 집을 짓는 것과 같습니다. 클래스는 설계 도면과 같으며 방 수, 방 크기 및 기능 등을 계획합니다. 건물이 존재한다고 해도 사람이 살 수는 없습니다. 설계 도면으로 지어야 집이 살 수 있습니다. 동일한 클래스는 설계 도면과 같으며 데이터를 저장할 수 없습니다. 인스턴스화된 객체는 데이터를 저장하기 위해 물리적 메모리를 할당합니다.
클래스 객체에 어떤 멤버가 있는지 분석해 보세요. 클래스에 의해 인스턴스화된 각 객체는 독립적인 데이터 공간을 가지므로 객체에는 멤버 변수가 포함되어야 합니다. 그러면 멤버 함수가 포함됩니까? 첫째, 함수가 컴파일된 후에는 객체에 저장할 수 없는 명령어 섹션입니다. 이러한 명령어는 별도의 영역(코드 세그먼트)에 저장되므로 객체에 저장해야 하는 경우에만 가능합니다. 멤버 함수에 대한 포인터. 다시 분석해 보겠습니다. 객체에 포인터를 저장해야 합니까? Date는 두 객체 d1과 d2를 인스턴스화합니다. d1과 d2 모두 자체 데이터를 저장하기 위해 자체 독립 멤버 변수 _year/_month/_day를 가지고 있지만 멤버 함수 Init/Print d1과 d2의 포인터는 동일하므로 객체에 저장하는 것은 낭비입니다. Date를 사용하여 100개의 개체를 인스턴스화하면 멤버 함수 포인터가 100번 저장되므로 너무 낭비됩니다. 실제로 함수 포인터는 저장할 필요가 없습니다. 호출하는 함수는 어셈블리 명령어[호출 주소]로 컴파일됩니다. 실제로 컴파일러는 컴파일하고 링크할 때 함수의 주소를 찾아야 합니다. , 런타임에는 없습니다. 런타임에는 동적 다형성만 발견되며 함수 주소를 저장해야 합니다.
위에서 우리는 멤버 변수만이 객체에 저장된다는 것을 분석했습니다. C++에서는 클래스에 의해 인스턴스화되는 객체도 메모리 정렬 규칙을 준수해야 한다고 규정합니다.
메모리 정렬 규칙
메모리 정렬 규칙은 C 언어의 정렬 규칙과 완전히 동일합니다.참고 기사:메모리 정렬을 계산하는 C 언어
첫 번째 멤버는 구조체의 주소 오프셋 0에 있습니다.
• 다른 멤버 변수는 특정 숫자(정렬 번호)의 정수배인 주소에 매핑되어야 합니다.
• 참고: 로그 = 컴파일러의 기본 정렬 번호와 멤버 크기 중 작은 값입니다.
•VS의 기본 로그는 8입니다.
• 구조의 전체 크기는 최대 정렬 수(모든 변수 유형 중 가장 큰 값과 가장 작은 기본 정렬 매개변수)의 정수 배수입니다.
• 구조가 중첩되고 중첩된 구조가 자체 최대 로그의 정수 배수로 정렬되는 경우 구조의 전체 크기는 모든(중첩 구조의 정렬 포함) 숫자 중 최대 정렬 수입니다.
멤버 변수가 없으면 1바이트를 주어야 하는데, 1바이트도 주어지지 않으면 객체가 존재했다는 것을 어떻게 알 수 있겠는가? 따라서 여기에는 객체 존재의 자리 표시자 식별을 위해 순수하게 1바이트가 제공됩니다.
Date 클래스에는 두 개의 멤버 함수인 Init와 Print가 있습니다. 함수 본문에는 서로 다른 객체가 있습니다. 따라서 d1이 Init 및 Print 함수를 호출할 때 함수는 d1 객체에 액세스해야 하는지 또는 액세스해야 하는지 어떻게 알 수 있습니까? d2 객체?그런 다음 여기서는 C++에서 문제를 해결하기 위해 암시적으로 this 포인터를 제공하는 것을 볼 수 있습니다.
• 컴파일러가 컴파일된 후 클래스의 멤버 함수는 기본적으로 이 포인터라고 하는 현재 클래스 유형의 포인터를 형식 매개 변수의 첫 번째 위치에 추가합니다. 예를 들어 Init of Date 클래스의 실제 프로토타입은 다음과 같습니다.void Init(Date* const this, int year, int Month, int day) • 클래스 멤버 함수에서 멤버 변수에 액세스할 때 기본적으로 이 포인터를 통해 액세스됩니다. ->_연도 = 연도;
• 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;
- }