2024. 3. 18. 10:15ㆍProgramming Language/C++
아래 링크 클릭 시 해당 본문으로 이동
멤버 함수
• 클래스가 사용하는 전용 함수 (클래스 내부에 정의된 함수)
• 클래스의 객체가 필요하다.
멤버 함수를 호출하려면 해당 클래스의 실체화가 되어있는 변수인 객체가 필요하다.
• 멤버 함수를 객체를 통해서 호출하면 해당 객체의 주소가 this 포인터로 전달된다.
this 포인터
클래스의 멤버 함수를 호출 시 호출할 객체(instance, 인스턴스)를 찾으려면 this 포인터를 사용해야 한다.
• 생략되어 있지만 모든 멤버 함수에 추가되어 있는 매개 변수로, 해당 멤버 함수를 호출한 객체의 주소를 가리키는 상수 포인터이다.
this 포인터에 저장된 주소(현재 객체의 주소)를 수정할 수 없지만, const로 표시되지 않으면 가리키는 개체를 수정할 수 있다.
• 멤버 변수 이름이 매개 변수(생성자, 멤버 함수)와 동일할 때 명시적으로 `this`를 사용하여 멤버 변수를 명확히 구분할 수 있다.
▷ 예시
#include <iostream>
using namespace std;
class MyClass {
private:
// 멤버 변수
int value;
int m_i;
float m_f;
public:
MyClass(int value) {
// 지역 변수와 멤버 변수를 구분하기 위해 this 사용하여 멤버 변수를 명확히 지정한다.
this->value = value;
// this->value는 멤버 변수이고, value는 매개 변수이다.
}
void SetInt(int i)
{
// m_i => public이고, 동일한 클래스 CMy이므로 사용 가능
m_i = i; // this 키워드가 생략되어있다. => this->m_i = i;
}
// ------- C언어 스타일로 작성한 SetInt() ------- //
//public:
// void SetInt(CMy* _this, int i)
// {
// _this->m_i = i; // SetInt()를 호출할 객체의 주소를 받아와서 그것의 멤버에 세팅한다는 뜻이다.
// }
};
int main() {
MyClass mc;
mc.SetInt(10); // mc.SetInt(&mc, 10);
return 0;
}
`mc.SetInt(10);`를 호출하면 컴파일러는 `mc.SetInt(&mc, 10);`으로 변환해서 호출한다.
`setInt()` 멤버 함수 내에서 this 포인터는 객체 `mc`의 주소를 가리킨다.
`SetInt()` 내부의 모든 멤버 변수 앞에는 `this->`가 붙으므로 `m_i = i;`는 실제로는 `this->m_i = i;`으로 변환된다.
따라서 this->m_i는 mc->m_i가 된다.
위 과정들은 컴파일러가 자동으로 해주는 부분이기 때문에 전부 다 기억하지 않아도 되지만, 모든 멤버 함수에는 호출된 객체를 가리키는 this 포인터가 생략되어 있다는 것을 알고 있어야 한다.
함수 체이닝
• 여러 함수 호출을 단일 명령문으로 함께 연결할 수 있는 방법
이는 멤버 함수가 현재 개체(`*this`)에 대한 참조를 반환하도록 할 수 있다.
• `*this`를 반환하면 동일한 명령문의 동일한 객체에 대해 다른 함수를 호출할 수 있다.
// 여러 함수를 개별적으로 호출함.
obj.Function1();
obj.Function2();
obj.Function3();
// 아래처럼 같이 연결할 수 있다.
obj.Function1().Function2().Function3();
▷ 예시
#include <iostream>
using namespace std;
class MyClass {
private:
// 멤버 변수
int value;
public:
// *this, 함수 체이닝
public:
// 값 설정
MyClass& SetValue(int v) {
this->value = v;
return *this; // 현재 객체를 반환
}
// 덧셈
MyClass& Add(int v) {
this->value += v;
return *this; // 현재 객체를 반환
}
// 곱셈
MyClass& Multiply(int v) {
this->value *= v;
return *this; // 현재 객체를 반환
}
// 현재 값 출력
void Display() const {
cout << "값 : " << value << endl;
}
};
int main() {
MyClass mc2;
// 함수 체이닝
mc2.SetValue(10).Add(5).Multiply(3).Display(); // (10 + 5) * 3 = 45
return 0;
}
▽ 출력 결과
45
클래스(Class)
구조체가 내가 만든 자료형인 것처럼 클래스도 원하는 멤버로 만든 자료형이다.
생성자
• 객체가 생성될 때 자동으로 호출되는 멤버 함수이다.
• 클래스는 생성자라는 초기화(초기값을 줄뿐 문법적으로 진짜 초기화는 아니다.) 함수를 제공한다.
단, 초기값을 줄뿐 문법적으로 진짜 초기화는 아니다.
객체가 만들어짐과 동시에 값이 주어지는 것을 의미하며, 이미 객체가 만들어진 상황에서는 초기화가 아니다.
• 생성자 이름은 클래스 이름과 동일하고, 반환 타입이 없다.
• 각 멤버들이 처음에 어떤 값을 받을지 작성해 놓으면 신경 쓰지 않아도 객체가 만들어지면 자동으로 호출된다.(자동이라고 표현했지만 실제로는 컴파일러가 해 준다.)
• 생성자는 이니셜라이저(initializer)라는 초기화 문법을 제공한다.
이니셜라이저가 여러 개 일 때 `,`를 사용하여 옆으로 이어서 작성해도 되지만 아래로 작성하는 것이 가독성이 더 좋다.
멤버 작성 순서대로 이니셜라이저도 순차적으로 해주는 것이 좋다.
CMy()
// 이니셜라이저 (생성자에서 멤버 변수 초기화)
//: m_i(100), m_f(0.5f)
: m_i(100)
, m_f(0.5f)
{
}
• 생성자가 호출되면서 해당 객체의 멤버들을 지정한 값으로 초기화한다.
소멸자
• 객체가 소멸될 때 자동으로 호출되는 멤버 함수로, 필요한 정리 작업을 수행하는 데 사용된다.
소멸자가 호출되지 않으면 자원 해제가 이루어지지 않거나 정리 작업이 누락될 수 있다.
• 주로 객체가 소멸될 때 동적으로 할당된 메모리를 해제하거나, 파일 또는 데이터베이스 연결을 끊는 등의 작업을 처리한다.
• 소멸자는 클래스 이름 앞에 `~`를 붙인다.
• 소멸자는 반환값이나 매개변수를 가질 수 없다.
• 생성자가 객체의 초기화 작업을 담당하는 것과 마찬가지로, 소멸자는 객체가 더 이상 필요 없을 때 자원을 정리하고 메모리를 해제하는 등의 작업을 담당한다.
▷ 예시 (생성자, 소멸자)
class CMy() // 구조체라면 CMy는 인자가 2개(객체, 객체에 넣을 값)가 있어야 하지만, 클래스는 구조체와는 다르다.
{
public:
// 기본 생성자
CMy()
// 이니셜라이저
: m_i(100)
, m_f(0.5f)
{
//m_i = 100;
// 이는 멤버 변수의 초기화가 아니라 할당을 한 것이므로 초기화하려면 이니셜라이저를 이용해야 한다.
}
// 기본 소멸자
~CMy()
{
// 코드 내용 생략
}
};
int main()
{
CMy c; // CMy의 객체인 c가 생성되는 과정에서 CMy 클래스의 기본 생성자가 호출된다.
return 0;
// 클래스의 객체 c는 지역 변수이므로 main() 함수가 종료될 때 없어진다.
// main() 함수가 끝나는 부분(return 0;)에 중단점 걸어놓고 F11을 눌러보면 소멸자가 호출되는 것을 볼 수 있다.
}
생성자와 소멸자는 C++ 문법상 반드시 존재해야 된다.
직접 작성하지 않은 경우, 코드 상으로 보이지는 않지만 컴파일러가 자동으로 만들어준다.
이를 디폴트(기본) 생성자, 디폴트 소멸자라고 한다.
단, 컴파일러가 기본적으로 만들어주는 기본 생성자와 기본 소멸자는 아무 기능이 없다.
다시 말해, 생성자는 초기화 부분이 없고, 소멸자도 아무 일도 하지 않는다.
실수를 방지하는 법 2가지
1. 하지 말아야 하는 것을 제한하는 경우
2. 해야 되는 것을 까먹지 않게 하는 경우
'Programming Language > C++' 카테고리의 다른 글
[C++] namespace, using, 입출력 구현 (cin, cout) (0) | 2024.03.19 |
---|---|
[C++] 구조체 · 클래스 템플릿으로 리스트 구현 (0) | 2024.03.18 |
[C++] 정렬과 버블 정렬 구현, 함수 포인터 (0) | 2024.03.17 |
[C/C++] 연결 리스트 구현 (0) | 2024.03.17 |
[C++] 가변 배열 (0) | 2024.03.17 |