728x90
[Do it C++ 완전정복_ 252~275]
생성자(Constructor)
객체가 생성될 때 자동으로 호출되어 멤버 변수를 초기화하는 특별한 함수
- 클래스의 이름과 동일하며 반환형이 없다.
- 생성자 오버로딩이 가능하며 전달된 인자에 따라 생성자가 자동 호출된다. (→ 인자 전달시 기본 생성자 호출 X)
class Car {
private:
int speed;
public:
Car() { speed = 0; } // 기본 생성자
Car(int s) { speed = s; } // 매개변수 생성자
};
생성자 호출 순서
부모 클래스 → 자식 클래스 순서
- 상속받은 클래스의 객체가 생성될 때는 부모 클래스 → 자식 클래스 순서로 생성자 호출이 이루어진다.
- 자식 클래스가 부모의 속성을 포함하므로, 부모 부분이 먼저 초기화되어야 자식 객체가 완전한 상태가 된다.
맴버 변수 초기화 방법 (2가지)
초기화 목록은 객체 생성 시점에 값을 넣고, 대입문은 객체가 생성된 후에 값을 넣는다.
- 초기화 목록: 생성자 선언부 뒤 콜론(:) 에서 초기화됨
- 상수(const) 멤버, 참조형 멤버 초기화 가능
- 생성자 본문이 실행되기 전에 초기화가 완료됨
- 대입문: 생성자 본문 내부에서 초기화됨
복사 생성자 (Copy Constructor)
- 하나의 객체를 같은 클래스의 다른 객체로 복사할 때 호출되는 생성자이다.
- 반드시 매개변수로 동일 클래스 타입의 참조(reference)를 사용해야 하며, 일반적으로 const 를 붙인다.
(값 전달 방식으로 매개변수를 받으면 복사 생성자가 무한 재귀 호출됨)
복사 생성자 선언
클래스이름(const 클래스이름 &참조변수);
복사 생성자 구현
class Point {
private:
int x;
public:
Point(int n) : x(n) {} // 일반 생성자
Point(const Point& p) { x = p.x; } // 복사 생성자
};
복사 생성자 사용 이유
객체 내부에 동적 할당된 메모리 포인터가 있을 때 두 객체가 같은 주소를 가리키게 된다.
프로그램 종료 시 두 객체 모두 delete ptr 실행되어 오류가 발생하므로 사용자 정의 복사 생성자로 깊은 복사를 직접 구현해야한다.
오류 - 얕은 복사 예시
class Data {
private:
int* ptr;
public:
Data(int val) { ptr = new int(val); }
~Data() { delete ptr; }
};
int main() {
Data d1(10);
Data d2 = d1; // 기본 복사 생성자 → 얕은 복사 발생
}
해결 - 깊은 복사 예시
class Data {
private:
int* ptr;
public:
Data(int val) { ptr = new int(val); }
// 깊은 복사 생성자
Data(const Data& d) {
ptr = new int(*d.ptr); // 새로운 메모리 공간에 값 복사
}
~Data() { delete ptr; }
void show() { cout << *ptr << endl; }
};
int main() {
Data d1(10);
Data d2 = d1; // 복사 생성자 호출 (깊은 복사)
d2.show(); // 10
}
소멸자(Destructor)
객체의 수명이 끝날 때 자동으로 호출되는 함수로 동적 메모리 해제나 자원 반환 등의 정리 작업을 수행한다.
- 클래스 이름 앞에 ~ 를 붙여 정의하며 반환형과 매개변수가 없다.
- 프로그램 종료, 블록(scope) 종료, delete 호출 시 자동으로 실행
- 하나의 클래스에 하나만 존재
#include <iostream>
using namespace std;
class Car {
public:
Car() { cout << "생성자 호출" << endl; }
~Car() { cout << "소멸자 호출" << endl; }
};
int main() {
Car c; // 생성자 호출
} // 블록 종료 시 자동으로 소멸자 호출
주의: 상속 클래스에서 다형성을 사용할 때는 반드시 virtual 소멸자를 사용해야 한다.
가상 소멸자
부모 클래스의 소멸자를 virtual로 선언하면, delete 시 객체의 실제 타입(자식 클래스)의 소멸자까지 호출된다
자식 클래스의 소멸자가 호출되지 않으면 메모리 누수가 발생한다.
class Parent {
public:
virtual ~Parent() { cout << "부모 소멸자" << endl; }
};
class Child : public Parent {
public:
~Child() { cout << "자식 소멸자" << endl; }
};
int main() {
Parent* p = new Child();
delete p; // 자식 → 부모 순서로 소멸
}'C++ > C++ 문법' 카테고리의 다른 글
| C++ 오버로딩 (Overloading) (0) | 2025.10.14 |
|---|---|
| C++ 멤버 함수와 this 포인터 (0) | 2025.10.14 |
| C++ 다형성 개념과 다형성 구현 (팩토리 클래스, 오버라이딩) (0) | 2025.10.14 |
| C++ 바인딩 (Binding) (0) | 2025.10.14 |
| C++ 상속성 개념 및 다중 상속 (0) | 2025.10.14 |