기본 생성자
1. 개요
기본 생성자는 C++, Java, C# 등 프로그래밍 언어에서 클래스의 객체를 초기화하는 데 사용되는 특수한 생성자이다. C++에서는 인자 없이 호출될 수 있는 생성자를 기본 생성자로 정의하며, 컴파일러가 명시적으로 정의된 생성자가 없을 경우 암묵적으로 생성한다. C++11부터는 `= default`와 `= delete`를 사용하여 기본 생성자의 생성을 제어할 수 있다. Java와 C#에서는 클래스에 생성자가 정의되지 않은 경우 컴파일러가 자동으로 생성하는 무인자 생성자를 기본 생성자라고 한다.
-
메소드 (컴퓨터 프로그래밍) -
소멸자 (컴퓨터 프로그래밍)
소멸자는 객체가 메모리에서 제거되기 직전에 호출되는 멤버 함수로, 객체 자원 해제 및 정리 작업을 수행하며, C++ 등 여러 언어에서 구현되고 메모리 누수 방지에 기여한다. -
메소드 (컴퓨터 프로그래밍) -
동적 디스패치
동적 디스패치는 프로그램 실행 시 호출할 메서드를 결정하는 메커니즘으로, 단일 또는 다중 객체 기준으로 선택하며, 유연성과 확장성을 높이지만 성능 오버헤드를 발생시킬 수 있다. -
제어 흐름 -
프로그램 카운터
프로그램 카운터는 CPU 내에서 다음에 실행될 명령어의 주소를 저장하는 레지스터로, 명령어 사이클의 fetch 단계에서 사용되어 명령어를 가져오고 실행 후 갱신되며, CPU 성능 향상 기술과 현대 프로그래밍 모델에 영향을 미친다. -
제어 흐름 -
예외 처리
예외 처리는 프로그램 실행 중 예외 발생 시 정상적인 실행 흐름을 유지하거나 안전하게 종료하기 위한 메커니즘으로, 많은 프로그래밍 언어에서 제공하며 예외 안전성을 목표로 한다. -
객체 지향 프로그래밍 -
Is-a
Is-a 관계는 객체 지향 프로그래밍에서 한 유형이 다른 유형의 하위 유형임을 나타내는 관계로, 상속, 서브타이핑, 리스코프 치환 원칙과 관련되며, C++, Python, Java 등에서 표현된다. -
객체 지향 프로그래밍 -
객체 (컴퓨터 과학)
객체는 객체 지향 프로그래밍에서 데이터와 조작을 묶어 메시지를 수신하고, 프로그램의 개념을 표현하며 가시성과 재사용성을 높이는 실체이다.
2. C++
C++컴파일러는 클래스에 명시적으로 정의된 생성자가 없을 때 기본 생성자를 암묵적으로 선언하고 정의한다. 이 암묵적으로 정의된 기본 생성자는 빈 바디와 함께 명시적으로 정의된 것과 동일하다. 만약 클래스에 명시적으로 정의된 생성자가 있지만, 모두 기본 생성자가 아니라면, 컴파일러는 암시적으로 기본 생성자를 정의하지 않는다. 이는 클래스가 기본 생성자를 갖지 않는 상황으로 이어진다.
C++에서 기본 생성자는 다음과 같은 특정 상황에서 자동적으로 작동되므로 중요하다.
* 객체 값이 인자 목록 없이 정의되거나(`MyClass x;`) 인자 목록 없이 동적으로 할당될 때 (`new MyClass;` 또는 `new MyClass();`)
* 객체들의 배열이 정의되거나(`MyClass x[10];`) 동적으로 할당될 때 (`new MyClass [10]`)
* 상속하는 클래스 생성자가 자신의 초기화 리스트에서 명시적으로 베이스 클래스 생성자를 호출하지 않을 때
* 클래스 생성자가 자신의 초기화 리스트에서 객체 값을 갖는 것 중 하나의 생성자를 명시적으로 호출하지 않을 때
* 표준 라이브러리에서, 값이 명시적으로 주어지지 않았을 때 특정한 컨테이너가 기본 생성자를 사용해서 값을 채울 때
프로그래머와 컴파일러 모두 기본 생성자를 정의하지 않으면, 객체 생성 시 오류가 발생한다.
C++11에서는 `= default`를 사용하여 기본 생성자를 명시적으로 생성하거나, `= delete`를 사용하여 명시적으로 금지할 수 있다.
2.1. 기본 생성자의 정의와 호출
C++ 표준에서는 인자 없이 호출할 수 있는 생성자를 기본 생성자로 정의한다. 여기에는 모든 매개변수에 기본값이 있는 생성자도 포함된다.
예를 들면 다음과 같다.
```cpp
class MyClass
{
public:
MyClass(); // 생성자 선언
private:
int x;
};
MyClass::MyClass() : x(100) // 생성자 정의
{
}
int main()
{
MyClass m; // 런타임에 객체 m이 생성되고 기본 생성자가 호출됨
}
```
위의 코드에서 `MyClass()`는 인자가 없는 기본 생성자이다.
메모리를 동적으로 할당할 때, 클래스 이름 뒤에 괄호를 추가하여 기본 생성자를 명시적으로 호출할 수 있다.
```cpp
int main()
{
MyClass * pointer = new MyClass(); // 런타임에 객체가 생성되고 기본 생성자가 호출됨
}
```
생성자에 하나 이상의 매개변수가 있지만, 모두 기본값을 가지는 경우도 기본 생성자에 해당한다.
```cpp
class MyClass
{
public:
MyClass (int i = 0, std::string s = ""); // 생성자 선언
private:
int x;
int y;
std::string z;
};
MyClass::MyClass(int i, std::string s) // 생성자 정의
{
x = 100;
y = i;
z = s;
}
```
위의 코드에서 `MyClass (int i = 0, std::string s = "")`는 모든 매개변수가 기본값을 가지므로 기본 생성자이다.
2.2. 기본 생성자의 중요성
C++에서 기본 생성자는 특정 상황에서 자동으로 호출되기 때문에 중요하다. 이러한 상황에서 클래스에 기본 생성자가 없으면 오류가 발생한다. 기본 생성자가 필요한 경우는 다음과 같다.
* 객체가 인자 없이 정의되거나(예: `MyClass x;`) 인자 없이 동적으로 할당될 때 (예: `new MyClass;` 또는 `new MyClass();`), `MyClass`의 기본 생성자가 객체를 초기화하는 데 사용된다.
* 객체 배열이 정의될 때 (예: `MyClass x[10];`) 또는 동적으로 할당될 때 (예: `new MyClass [10]`), `MyClass`의 기본 생성자가 모든 요소를 초기화하는 데 사용된다.
* 상속하는 클래스 생성자가 자신의 초기화 리스트에서 명시적으로 베이스 클래스 생성자를 호출하지 않으면, 베이스 클래스의 기본 생성자가 호출된다.
* 클래스 생성자가 자신의 초기화 리스트에서 객체 값을 갖는 필드 중 하나의 생성자를 명시적으로 호출하지 않으면, 해당 필드 클래스의 기본 생성자가 호출된다.
* 표준 라이브러리에서 특정 컨테이너는 명시적으로 값이 주어지지 않은 경우 기본 생성자를 사용하여 값을 채운다. (예: `vector
클래스에 명시적으로 정의된 생성자가 없다면, 컴파일러는 기본 생성자를 암묵적으로 선언하고 정의한다. 이 암묵적으로 정의된 기본 생성자는 빈 몸체와 함께 명시적으로 정의된 것과 동일하다.
클래스에 명시적으로 정의된 생성자가 있지만, 모두 기본 생성자가 아니라면, 컴파일러는 암시적으로 기본 생성자를 정의하지 않는다. 이는 클래스가 기본 생성자를 갖지 않는 상황으로 이어져 오류를 발생시킨다.
2.3. 컴파일러에 의한 기본 생성자 자동 생성
C++에서 클래스에 명시적으로 정의된 생성자가 없는 경우, 컴파일러는 자동으로 기본 생성자를 생성한다. 이 암묵적으로 정의된 기본 생성자는 빈 몸체(body)를 가진 명시적으로 정의된 생성자와 동일하다.
```cpp
class MyClass
{
int x; // 생성자가 없으므로 컴파일러는 (암시적) 기본 생성자를 생성합니다.
};
int main()
{
MyClass m; // 런타임 오류 없음: (암시적) 기본 생성자가 호출됩니다.
}
```
반면, 클래스에 명시적으로 정의된 생성자가 있지만 모두 기본 생성자가 아닌 경우, 컴파일러는 암시적으로 기본 생성자를 정의하지 않는다. 이는 클래스에 기본 생성자가 없는 상황을 초래하며, 흔히 오류로 이어진다.
```cpp
class MyClass
{
public:
MyClass (int y); // 비-기본 생성자 선언
private:
int x;
};
MyClass::MyClass (int y)
{
x = y;
}
int main()
{
MyClass m(100); // 비-기본 생성자가 호출됩니다.
MyClass * p; // 포인터 선언의 경우, 컴파일러는 생성자에 대해 알 필요가 없습니다.
p = new MyClass(); // 컴파일 시 오류: 기본 생성자 없음.
return 0;
}
2.4. C++11에서의 기본 생성자 제어
C++11에서는 `= default`를 사용하여 기본 생성자를 명시적으로 생성할 수 있다.
```cpp
class MyClass
{
public:
MyClass() = default; // 기본 생성자 생성을 강제합니다.
};
```
`= delete`를 사용하여 기본 생성자 생성을 명시적으로 금지할 수도 있다.
```cpp
class MyClass
{
public:
MyClass() = delete; // 기본 생성자 생성을 방지합니다.
};
3. Java 및 C#
자바와 C#에서 기본 생성자는 클래스에 생성자가 정의되지 않은 경우 컴파일러가 자동으로 생성하는 무인자 생성자이다.