목차
- C 언어는 프로세스 지향적 이며 프로세스 에 중점을 두고 문제 해결 단계를 분석하고 함수 호출을 통해 점진적으로 문제를 해결합니다.
- C++ 는 객체지향을 기반으로 객체 에 초점을 맞추고 있으며 , 하나의 객체를 여러 객체로 분할하고 객체 간의 상호작용에 의존합니다. C++가 객체지향 언어를 기반으로 하는 이유 C++는 객체지향일 뿐만 아니라 프로세스지향도 가능하므로 하이브리드로 간주됩니다. 둘째, C++는 C 언어와 호환되어야 합니다.
- c 언어 구현 스택:
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int STDateType;
typedef struct Stack
{
STDateType* arr;
int top;
int capacity;
}ST;
void StackInit(ST* ps);//初始化
void StackDestory(ST* ps);//销毁
void StackPush(ST* ps, STDateType x);//压栈
void StackPop(ST* ps);//出栈
STDateType StackTop(ST* ps);//取栈顶元素
bool StackEmpty(ST* ps);//判断栈是否为空
int StackSize(ST* ps);//获取栈元素个数
#include"Stack.h"
void StackInit(ST* ps)//初始化
{
assert(ps);
ps->arr = NULL;
ps->top = 0;
ps->capacity = 0;
}
void StackDestory(ST* ps)//销毁
{
assert(ps);
free(ps->arr);
ps->arr = NULL;
ps->top = ps->capacity = 0;
}
void StackPush(ST* ps, STDateType x)//压栈
{
assert(ps);
if (ps->top == ps->capacity) //扩容
{
int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
STDateType* tmp = (STDateType*)realloc(ps->arr, sizeof(STDateType) * newCapacity);
if (tmp == NULL)
{
perror("realloc");
exit(-1);
}
ps->arr = tmp;
ps->capacity = newCapacity;
}
ps->arr[ps->top] = x;//尾插
ps->top++;
}
void StackPop(ST* ps)//出栈
{
assert(ps);
assert(!StackEmpty(ps));
ps->top--;
}
STDateType StackTop(ST* ps)//取栈顶元素
{
assert(ps);
assert(!StackEmpty(ps));//ps->top != 0
return ps->arr[ps->top - 1];
}
bool StackEmpty(ST* ps)//判断栈是否为空
{
assert(ps);
return ps->top == 0;
}
int StackSize(ST* ps)//获取栈元素个数
{
assert(ps);
return ps->top;
}
- C++ 구현 스택:
typedef int DataType;
struct Stack
{
void Init(size_t capacity)
{
_array = (DataType*)malloc(sizeof(DataType) * capacity);
if (nullptr == _array)
{
perror("malloc申请空间失败");
return;
}
_capacity = capacity;
_size = 0;
}
void Push(const DataType& data)
{
// 扩容
_array[_size] = data;
++_size;
}
DataType Top()
{
return _array[_size - 1];
}
void Destroy()
{
if (_array)
{
free(_array);
_array = nullptr;
_capacity = 0;
_size = 0;
}
}
DataType* _array;
size_t _capacity;
size_t _size;
};
약간의 지식: 위 구조의 정의는 C++ 의 클래스 로 대체되는 것이 좋습니다.
class className
{
// 类体:由成员函数和成员变量组成
}; // 一定要注意后面的分号
- class 는 클래스를 정의하는 키워드이고 , ClassName 은 클래스 이름, {} 는 클래스의 본문이며, 클래스 정의 마지막에는 세미콜론을 생략할 수 없습니다 .
- 클래스 본문에 있는 내용을 클래스의 멤버라고 합니다. 클래스에 있는 변수를 클래스의 속성 또는 멤버 변수 라고 합니다 . 클래스에 있는 함수를 클래스 의 메서드 또는 멤버 함수 라고 합니다.
지식이 거의 없음: 클래스 이름도 유형을 나타냅니다. 예:
- public 으로 수정된 멤버는 클래스 외부에서 직접 접근 가능
- Protected 및 private 수정된 멤버는 클래스 외부에서 직접 액세스할 수 없습니다 ( 여기서 protected 및 private은 유사합니다 ).
- 액세스 범위는 이 액세스 한정자가 발생할 때 시작하고 다음 액세스 한정자가 발생할 때 끝납니다.
- 나중에 액세스 한정자가 없으면 범위는 클래스의 끝인 }에서 끝납니다.
- 클래스의 기본 접근 권한은 private 이고 struct는 public 입니다 ( struct는 C 와 호환되어야 하기 때문입니다 ).
참고: 액세스 한정자는 컴파일 타임에만 유용하며, 데이터가 메모리에 매핑되면 액세스 한정자에는 차이가 없습니다.
팁:
- C++는 C 언어 와 호환되어야 하므로 C++ 의 struct를 구조체로 사용할 수 있습니다. 또한 C++ 의 구조체를 사용하여 클래스를 정의할 수도 있습니다. 클래스를 정의하는 클래스 와 동일하며 , struct 로 정의된 클래스의 기본 접근 권한은 public 이고, class로 정의된 클래스 의 기본 접근 권한 은 private이라는 점이 다릅니다 .
- 캡슐화(Encapsulation): 데이터와 데이터를 조작하는 방법을 유기적으로 결합하고, 객체의 속성과 구현 세부 사항을 숨기고, 객체와 상호 작용할 수 있는 인터페이스만 노출합니다 .
- 캡슐화는 본질적으로 사용자가 클래스를 더 쉽게 사용할 수 있도록 하는 일종의 관리입니다 . 예: 컴퓨터와 같은 복잡한 장치의 경우 사용자 전원 켜기/끄기 버튼, 키보드 입력, 모니터, USB 잭 등이며, 이를 통해 사용자는 컴퓨터와 상호 작용하고 일상 . 그러나 실제로 컴퓨터의 실제 작업은 CPU , 그래픽 카드, 메모리 및 기타 하드웨어 구성 요소입니다.
- 컴퓨터 사용자의 경우 마더보드의 회로 배치, CPU 내부 설계 등 내부 핵심 구성 요소에 대해 걱정할 필요가 없습니다. 사용자는 컴퓨터를 켜는 방법과 방법만 알면 됩니다. 키보드와 마우스를 통해 컴퓨터와 상호 작용합니다 . 따라서 컴퓨터 제조업체는 공장을 떠날 때 내부 구현 세부 사항을 숨기기 위해 외부에 쉘을 배치하고 사용자가 컴퓨터와 상호 작용할 수 있도록 전원 스위치, 마우스 및 .
- C ++ 언어 에서 캡슐화를 구현하기 위해서는 데이터를 연산하기 위한 데이터와 메소드를 클래스를 통해 유기적으로 결합할 수 있고, 접근 권한을 이용해 객체의 내부 구현 내용을 숨기고 클래스 외부에서 직접 어떤 메소드를 사용할 수 있는지 제어할 수 있다 .
class Person
{
public:
void PrintPersonInfo();
private:
char _name[20];
char _gender[3];
int _age;
};
// 这里需要指定PrintPersonInfo是属于Person这个类域
void Person::PrintPersonInfo()
{
cout << _name << " "<< _gender << " " << _age << endl;
}
- 객체에는 클래스의 다양한 멤버가 포함되어 있습니다.
- 코드 사본은 1개만 저장되며, 코드가 저장된 주소가 객체에 저장됩니다.
- 멤버 변수만 저장되며, 멤버 함수는 공개 코드 섹션에 저장됩니다.
컴파일러는 일반적으로 세 번째 저장 방법인 테스트를 채택합니다.
7.2 학급 규모
클래스의 크기는 실제로 클래스에 있는 " 멤버 변수 " 의 합입니다. 멤버 함수 는 클래스에 들어가지 않으므로 클래스 공간의 크기를 차지하지 않습니다. 멤버 변수는 메모리 정렬 규칙을 따릅니다. 또한, 빈 클래스의 크기에 주의하십시오. 빈 클래스는 특별합니다. 컴파일러는 이 클래스의 객체를 고유하게 식별하기 위해 빈 클래스에 바이트를 제공합니다.
메모리 정렬에 관하여:
이 구조 메모리 정렬 도 참조하세요 .
class Date
{
public:
void Init(int year, int month, int day)
{
this->_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;
d1.Init(2023, 9, 1);
d1.Print();
d2.Init(2023, 9, 2);
d2.Print();
return 0;
}
C++는 this 포인터를 도입하여 이 문제를 해결합니다 . 즉, C++ 컴파일러는 각 " 비정적 멤버 함수 " 에 숨겨진 포인터 매개 변수를 추가하여 포인터가 현재 객체 ( 함수가 호출될 때 함수를 호출하는 객체) 를 가리킬 수 있도록 합니다. is running ) 함수 본문의 "멤버 변수" 이 포인터를 통해 액세스됩니다. 모든 작업은 사용자에게 투명합니다. 즉, 사용자가 이를 전달할 필요가 없으며 컴파일러가 자동으로 완료합니다 .
- 이 포인터의 유형: 클래스 유형 * const , 즉 멤버 함수에서 이 포인터에는 값을 할당할 수 없습니다.
- " 멤버 함수 " 내 에서만 사용할 수 있습니다.
- this 포인터는 본질적으로 " 멤버 함수 " 의 형식 매개변수 입니다 . 개체가 멤버 함수를 호출하면 개체 주소가 실제 매개변수로 this 매개변수에 전달됩니다. 따라서 this 포인터는 객체에 저장되지 않습니다 .
- this 포인터는 " 멤버 함수 " 의 첫 번째 암시적 포인터 매개변수 입니다 . 일반적으로 컴파일러에 의해 ecx 레지스터를 통해 자동으로 전달 사용자가 전달할 필요가 없습니다.
// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:
void Print()
{
cout << this << endl;
cout << "Print()" << endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->Print();
return 0;
}
답: 함수가 공개 코드 영역에 있기 때문에 정상적으로 실행되는데, 포인터가 이 함수를 호출하더라도 포인터가 디코딩되지 않습니다.
// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:
void PrintA()
{
cout << _a << endl;
//cout << this->_a << endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->PrintA();
return 0;
}
답변: 널 포인터 문제로 인해 실행이 중단되었습니다. 널 포인터가 역참조되었습니다.
- 이 포인터는 형식 매개변수이고 형식 매개변수는 일반적으로 스택 영역에 저장되기 때문에 이것의 저장 위치는 스택 영역입니다.
- 하지만 이 포인터는 최적화될 수도 있습니다. vs는 레지스터에 저장되므로 특정 저장 위치는 컴파일러에 따라 다릅니다.
참고: 개념적 콘텐츠는 Bittech에서 제공됩니다.