[C++ 클래스 및 객체] 클래스에는 어떤 기본 멤버 함수가 있습니까? (우수한)

목차

1. 클래스의 6가지 기본 멤버 함수

2. 생성자(*^▽^*)

2.1 개념

2.2 특징

3. 소멸자 (*^▽^*)

3.1 개념

3.2 특징

4. 복사 생성자(*^▽^*)

4.1 개념

4.2 특징

5. 할당 연산자 오버로딩(*^▽^*)

5.1 연산자 오버로딩

5.2 할당 연산자 오버로딩


ヾ(๑╹◡╹)ノ" 과거의 나태함은 언제나 대가를 치러야 합니다!ヾ(๑╹◡╹)ノ"


1. 클래스의 6가지 기본 멤버 함수

클래스에 멤버가 없으면 단순히 빈 클래스라고 합니다.
비어있는 클래스에는 아무것도 없습니다.어떤 클래스도 아무 것도 쓰지 않으면 컴파일러는 자동으로 다음 6개의 기본 멤버 함수를 생성합니다.

 기본 멤버 함수: 사용자가 명시적으로 구현하지 않고 컴파일러에서 생성한 멤버 함수를 기본 멤버 함수라고 합니다.

2. 생성자 (*^▽^*)

2.1 개념

데이터 클래스의 경우:

class Date
{
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1;
	d1.Init(2022, 7, 5);//初始化
	d1.Print();
	Date d2;
	d2.Init(2022, 7, 6);//初始化
	d2.Print();
	return 0;
}

위 코드의 경우 Init public 메소드를 통해 오브젝트의 날짜를 설정할 수 있으며 , 이 메소드를 호출하여 오브젝트가 생성될 때마다 정보를 설정할 수 있습니다.

생성자는 클래스 이름과 같은 이름을 가진 특별한 멤버 함수로 , 데이터 멤버가 적절한 초기값을 갖도록 클래스 타입 객체를 생성할 때 컴파일러에 의해 자동으로 호출되며 , 평생 한 번만 호출 됩니다. 객체의 주기 .

2.2 특징

생성자 는 특수한 멤버 함수로, 생성자의 이름은 컨스트럭션이라고 하지만 생성자의 주된 임무는 객체를 생성하기 위한 공간을 여는 것이 아니라 객체를 초기화하는 것입니다 .
특징:
1. 함수 이름은 클래스 이름과 동일합니다.
2. 반환 값이 없습니다.
3. 컴파일러는 개체가 인스턴스화될 때 해당 생성자를 자동으로 호출합니다 .
4. 생성자는 오버로드될 수 있습니다. [하지만 우리가 작성하는 대부분은 기본 생성자이며 일반적으로 함수 오버로딩이 필요하지 않습니다[기본 생성자 + 기타 함수 오버로딩 작성]]
class Date
{
public:
	// 1.无参构造函数
	Date()//构造函数:函数名与类名相同,无返回值
	{
		_year = 1;
		_month = 1;
		_day = 1;
	}
	// 2.带参构造函数
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};
void TestDate()
{
	Date d1; // 调用无参构造函数,注意,不能写成Date d1();
	Date d2(2015, 1, 1); // 调用带参的构造函数
	// 注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明
}
5. 클래스에 명시적으로 정의된 생성자가 없으면 C++ 컴파일러는 매개변수 없이 자동으로 기본 생성자를 생성 합니다 .사용자가 컴파일러를 명시적으로 정의하면 더 이상 생성하지 않습니다 . [즉, 생성자가 구현되지 않은 경우 C++ 컴파일러는 매개 변수가 없는 기본 생성자를 자동으로 생성합니다.]

 기본 생성자: (1) 인수 없는 생성자 (2) 전체 기본 생성자 (3) C++ 컴파일러에서 생성한 인수 없는 생성자[즉, 기본 생성자가 없는 경우 셋 중 하나가 있어야 함] 작성된 생성자 매개변수가 없거나 모두 기본값이 아닙니다. 오류를 보고합니다.]

6. 컴파일러에 의해 생성된 기본 멤버 함수와 관련하여 생성자가 구현되지 않은 경우 컴파일러는 기본 생성자를 생성합니다. 하지만 기본 생성자가 쓸모없는 것 같습니까? 개체는 컴파일러에서 생성된 기본 생성자를 호출하지만 개체 _year/_month/_day 는 여전히 임의의 값입니다[내장 유형은 여전히 ​​임의의 값입니다] . 즉 , 컴파일러에 의해 생성된 기본 생성자는 여기서 쓸모가 없습니까?
답변: C++ 는 유형을 내장 유형 ( 기본 유형 ) 과 사용자 지정 유형으로 나눕니다. 내장 유형은 언어에서 제공하는 데이터 유형(예: int/char...)이고 사용자 정의 유형은 class/struct/union을 사용하여 정의한 유형 입니다. 생성자가 구현되지 않은 경우 컴파일러는 사용자 지정 형식의 멤버 에서 기본 멤버 함수를 호출하는 기본 생성자를 생성합니다.

클래스의 멤버가 모두 사용자 지정 유형인 경우 기본 생성 함수를 사용할 수 있습니다. 기본 제공 형식 함수 멤버가 있거나 매개 변수 초기화를 표시해야 하는 경우 생성자를 직접 구현해야 합니다. (초기화하려면 매개 변수를 전달해야 하며, 생성자를 직접 구현해야 합니다.) [대부분 스스로 생성자를 작성합니다.]

C++ 컴파일러에 의해 생성된 기본 생성자는 내장 유형 함수 멤버 변수를 처리하지 않으며 사용자 정의 유형 멤버는 자체 기본 생성자를 호출합니다.

참고: C++11 에서는 내장형 멤버가 초기화되지 않는 결함, 즉 내장형 멤버 변수가 클래스에서 선언될 때 기본값을 부여받을 수 있는 결함에 대한 패치가 패치되었습니다 . [참고: 이것은 선언이므로 초기화가 아닌 기본값입니다.]
7. 매개변수가 없는 생성자와 기본 생성자를 모두 기본 생성자라고 하며 기본 생성자는 하나만 있을 수 있습니다.
참고: 인수 없는 생성자, 전체 기본 생성자 및 기본적으로 컴파일러에서 생성되도록 작성하지 않은 생성자는 모두 기본 생성자로 간주될 수 있습니다.
class Date
{
public:
	Date()//无参的构造函数
	{
		_year = 1900;
		_month = 1;
		_day = 1;
	}
	Date(int year = 1900, int month = 1, int day = 1)//全缺省的构造函数
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

void Test()
{
	Date d1;//这里会发生错误,默认构造函数只能有一个
}

런타임에 오류가 발생하고 충돌이 발생합니다.

일반적으로 C++ 클래스는 자체 생성자를 작성해야 합니다. 컴파일러가 자동으로 생성하도록 할 수 있는 드문 경우가 있습니다.

(1) 클래스의 멤버는 모두 자체 정의 형식 멤버이며 이러한 멤버는 기본 생성자를 제공합니다.

(2) 빌트인 타입 멤버 선언 시 기본값이 주어진다.

3. 소멸자 (*^▽^*)

3.1 개념

소멸자 : 생성자의 기능과 달리 소멸자는 객체의 소멸을 완료 하지 않으며 로컬 객체의 소멸은 컴파일러에서 수행합니다. 개체가 소멸 되면 자동으로 소멸자를 호출하여 클래스의 일부 리소스 청소 작업을 완료합니다. 【파괴】

3.2 특징

소멸자는 특수 멤버 함수입니다.
특징:
1. 소멸자 이름은 클래스 이름 앞의 ~ 문자입니다 .
2. 매개변수 및 반환 값이 없습니다.
3. 클래스에는 단 하나의 소멸자가 있습니다. 명시적으로 정의되지 않은 경우 시스템은 자동으로 기본 소멸자를 생성합니다[사용자 지정 유형의 변수는 자체 소멸자를 호출하고 내장 유형의 변수는 처리되지 않습니다]. 참고: 소멸자는 오버로드
4. 개체 수명 주기가 끝나면 C++ 컴파일 시스템이 자동으로 소멸자를 호출합니다.
5.  컴파일러에 의해 자동으로 생성된 소멸자와 관련하여 컴파일러에 의해 생성된 기본 소멸자는 사용자 지정 형식 멤버에 대해 자체 소멸자를 호출합니다.
6. 클래스에 리소스 응용 프로그램이 없으면 소멸자를 작성할 수 없으며 Date 클래스와 같이 컴파일러에서 생성한 기본 소멸자를 직접 사용합니다. 리소스 응용 프로그램이 있으면 작성해야 합니다. 그렇지 않으면 스택 클래스 [간단히 말해서 리소스 응용 프로그램이 있으면 소멸자를 작성해야 함]와 같은 리소스 누출이 발생합니다 .

4. 복사 생성자 (*^▽^*)

4.1 개념

 객체가 생성되면 객체와 정확히 동일한 새 객체가 생성됩니다.

복사 생성자 : 이 클래스 유형의 개체 에 대한 참조 ( 일반적으로 const 데코레이션이 일반적 으로 사용됨 ) 형식 매개 변수는 하나뿐이며 기존 클래스 유형 개체 로 새 개체를 만들 때 컴파일러에서 자동으로 호출됩니다 .

4.2 특징

1. 복사 생성자는 생성자의 오버로드된 형식입니다 .

2. 복사 생성자는 매개 변수가 하나만 있고 참조 로 전달되어야 하며 으로 전달하는 방법은 무한 재귀 호출을 발생시킵니다 .
class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date(const Date& d)//拷贝构造函数
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1;
	Date d2(d1);
	return 0;
}

값 전달 방법: 복사 생성자를 호출하면 복사 생성자가 호출됩니다.이 함수를 호출하려면 매개 변수를 먼저 전달해야 합니다. 전달 매개 변수는 임시 복사본입니다 .이 때 상태는 임시 복사 개체이며 이는 복사 생성 함수를 호출해야 하며 이때 무한 재귀 호출이 트리거됩니다.

참조로 매개변수 전달 : 복사 생성이 호출되지 않습니다.

[객체가 이 클래스의 다른 객체를 초기화하는데, 이것이 복사 생성입니다.] [객체 복사는 복사 생성입니다.]

사용자 정의 유형 객체의 경우 복사 생성자를 호출하여 복사 초기화를 완료해야 합니다.

정의가 표시되지 않으면 시스템에서 기본 복사 생성자를 생성합니다. 기본 복사 생성자 개체는 메모리 저장 공간에 따라 바이트 순서로 복사되며 이러한 복사를 얕은 복사 또는 값 복사라고 합니다. [즉, 빌트인 타입의 멤버는 값 복사(얕은 복사)를 완료하고, 커스텀 타입의 멤버는 이 멤버의 복사 생성을 호출합니다.]
결론: 일반 수업의 경우 자체 생성 복사 구조로 충분하며 복사 구조를 직접 작성할 필요가 없습니다. 하지만 stack과 같이 리소스를 직접 관리하는 클래스의 경우 deep copy를 직접 구현해야 합니다.
4.  그러면 컴파일러에 의해 생성된 기본 복사 생성자가 이미 바이트 순서의 값 복사를 완료할 수 있습니다 . 여전히 직접 구현해야 합니까? 물론 Date 클래스와 같은 클래스는 불필요합니다. 스택과 같은 클래스는 허용되지 않습니다. [스택에 주소가 있으면 두 스택이 같은 공간으로 이동하고 추가, 삭제, 확인 및 수정시 서로 영향을 미칩니다. 파괴시 동일한 공간이 두 번 파괴되고 동일한 공간이 2번 공개됩니다. 프로그램이 무너질 것입니다-엔딩 솔루션, 복사 구성을 직접 구현-깊은 복사]
클래스에 포함된 리소스 응용 프로그램이 없는 경우 복사 생성자를 작성할 수도 있고 작성하지 않을 수도 있습니다.

 프로그램의 효율성을 높이기 위해 일반 객체에 파라미터를 넘길 때는 최대한 레퍼런스 타입을 사용하고, 돌아올 때는 실제 장면에 따라 최대한 레퍼런스를 사용하도록 한다.

5. 할당 연산자 오버로딩 (*^▽^*)

5.1 연산자 오버로딩

C++ 에서는 연산자 오버로딩을 도입하여 코드의 가독성을 높였습니다 . 연산자 오버로딩은 함수 이름이 특수한 함수이며 반환 값 유형, 함수 이름 및 매개 변수 목록도 있습니다. 반환 값 유형 및 매개 변수 목록은 일반 함수와 유사합니다. .
함수 이름은 다음과 같습니다 . 연산자 키워드 다음에 오버로드해야 하는 연산자 기호가 옵니다 .
함수 원형 : 반환 값 유형  연산자 연산자 ( 매개변수 목록 )
반환 값: 작업 결과
매개변수: 연산 피연산자
알아채다:
(1) operator@ 와 같은 다른 기호를 연결하여 새 연산자를 만들 수 없습니다.
(2) 오버로드된 연산자에는 클래스 유형 매개변수가 있어야 합니다.
(3) 내장 유형에 사용되는 연산자의 의미는 변경할 수 없습니다. 예: 내장 정수 +는 그 의미를 변경할 수 없습니다.
(4) 클래스 멤버 함수로 오버로드될 때 형식 매개 변수는 피연산자 수보다 1 적은 것처럼 보입니다 . 멤버 함수의 첫 번째 매개 변수는 숨겨진 this이기 때문입니다.
(5) .*     :: sizeof ?: . 위의 5개 연산자는 오버로드할 수 없습니다. 필기시험에서 자주 나옵니다.             
//日期的判断是否相等
bool operator==(const Date& d1, const Date& d2)
{
	return d1._year == d2._year 
		&& d1._month == d2._month 
		&& d1._day == d2._day;
 }
//放到类里面 Date,此时是在类外面的写法
//1.
if (operator==(d1, d2))
{
	cout << "==" << endl;
}
//2/
if (d1 == d2)
{
	cout << "==" << endl;
}
//1.和2.是等价的,编译器会处理成1.

(1) 빌트인 타입은 다양한 연산자를 직접 사용할 수 있지만 커스텀 타입은 다양한 알고리즘을 직접 사용할 수 없습니다. 사용자 정의 유형에서 다양한 연산자를 사용할 수 있도록 하기 위해 연산자 오버로딩이 있습니다.

(2) 피연산자 수만큼 함수 매개변수가 있습니다. (== 피연산자 2개; ++ 피연산자 1개;)

클래스에서 작성 :

//日期的判断是否相等
bool operator==(const Date& d)
{
	return _year == d._year
		&& _month == d._month
		&& _day == d._day;
}
//放到类里面 Date,此时是在类里面的写法
//1.
if (d1.operator==(d2))
{
	cout << "==" << endl;
}
//2/
if (d1 == d2)
{
	cout << "==" << endl;
}
//1.和2.是等价的,编译器会处理成对应重载运算法调用

두 코드가 모두 존재하는 경우(컴파일러는 함수 오버로드를 준수하므로 통과할 수 있음) 컴파일러는 먼저 클래스에서 연산자 오버로드를 사용합니다.

//判断日期小
bool operator<(const Date& d)
{
	//小的情况
	if (_year < d._year
		|| (_year == d._year && _month < d._month)
		|| (_year == d._year && _month == d._month && _day < d._day))
	{
		return true;
	}
	else
	{
		return false;
	}
}

당연한 것으로 여기지 말고 세부 사항에 주의를 기울이십시오.

5.2 할당 연산자 오버로딩

1. 매개변수 유형
2. 반환값
3. 자신에게 가치를 부여했는지 확인
4. 반환 *이
5. 클래스가 할당 연산자 오버로드를 명시적으로 정의하지 않는 경우 컴파일러는 객체의 바이트 순서 값 복사를 완료하기 위해 오버로드도 생성합니다.
1. 할당 연산자 오버로드 형식
매개변수 유형 : const T& , 참조에 의한 전달은 매개변수 전달의 효율성을 향상시킬 수 있습니다.
반환 값 유형 : T& , 반환 참조는 반환의 효율성을 향상시킬 수 있으며 반환 값의 목적은 지속적인 할당을 지원하는 것입니다.
자신에게 값을 할당했는지 확인
Return *this : 연속 할당의 의미를 합성합니다.
//d2 = d1;-> d2.operator(&d2, d1)
Date& operator=(const Date& d)
{
	if (this != &d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	return *this;
}
int main()
{

	Date d1(2000, 8, 20);
	Date d2(2000, 9, 17);
	Date d3(d1);//拷贝构造,一个存在的对象去初始化另一个要创建的对象
	d2 = d1;//赋值重载(复制拷贝) 两个已经存在的对象之间赋值
}
2. 할당 연산자는 클래스의 멤버 함수로만 오버로드할 수 있으며 전역 함수로 오버로드할 수 없습니다.
대입 연산자는 전역함수에 오버로딩된 상태로 전역함수에 오버로드시 this포인터가 없다는 점 참고하세요.매개변수는 2개가 필요하지만
할당 연산자가 명시적으로 구현되지 않은 경우 컴파일러는 기본 연산자를 생성합니다. 이 때 사용자는 전역을 구현합니다.
할당 연산자 오버로드는 클래스의 컴파일러에서 생성한 기본 할당 연산자 오버로드와 충돌하므로 할당 연산자 오버로드는 클래스의 멤버 함수만 될 수 있습니다 .
3. 사용자가 명시적으로 구현하지 않으면 컴파일러는 value 형식으로 바이트 단위로 복사되는 기본 할당 연산자 오버로드를 생성합니다 . 참고: 기본 제공 형식 멤버 변수는 직접 할당되지만 사용자 지정 형식 멤버 변수는 해당 클래스의 할당 연산자 오버로드를 호출하여 할당을 완료해야 합니다.
4. 컴파일러에 의해 생성된 기본 할당 오버로드 함수는 이미 바이트 순서 값을 복사할 수 있습니다 . 여전히 직접 구현해야 합니까? 물론 Date 클래스와 같은 클래스는 불필요합니다. 리소스 관리가 클래스에 포함되지 않은 경우 할당 연산자의 구현 여부는 중요하지 않으며 일단 리소스 관리가 포함되면 구현해야 합니다.

보충 지식: 널 포인터가 존재하지 않습니까? 존재하며 빈 주소는 기존 주소입니다.

Supongo que te gusta

Origin blog.csdn.net/m0_57388581/article/details/132179408
Recomendado
Clasificación