C++ 초급 - 8. 객체지향 프로그래밍 (6 - explicit 생성자 (C++11))
2025. 2. 22. 16:53ㆍ프로그래밍 언어/C++
📌 8.6 explicit 생성자 (C++11)
C++에서는 암시적 변환(Implicit Conversion)으로 인해 예기치 않은 객체 변환이 발생할 수 있다.
이를 방지하기 위해 explicit 키워드를 생성자 앞에 붙이면, 암시적 변환을 금지하고 명시적 변환만 허용할 수 있다.
이러한 기능을 활용하면 코드의 안전성을 높이고, 예측하지 못한 동작을 방지할 수 있다.
📌 1. 암시적 변환(Implicit Conversion)의 문제점
🔹 (1) 암시적 변환이란?
- C++에서는 단일 인자를 받는 생성자가 있을 경우, 해당 타입의 값을 자동 변환하여 객체를 생성할 수 있음.
- 즉, 클래스 객체가 명시적으로 생성되지 않아도 암시적으로 변환되어 객체가 만들어지는 문제가 발생할 수 있음.
💡 예제: 암시적 변환으로 발생하는 문제
#include <iostream>
class Distance {
private:
int meters;
public:
Distance(int m) { // ❌ explicit 미사용 → 암시적 변환 허용
meters = m;
std::cout << "Distance 객체 생성됨! (" << meters << "m)" << std::endl;
}
void show() { std::cout << "거리: " << meters << "m" << std::endl; }
};
int main() {
Distance d1 = 10; // ✅ int → Distance 변환 (암시적 변환 발생)
d1.show();
return 0;
}
🔹 출력 결과
Distance 객체 생성됨! (10m)
거리: 10m
💡 설명
- Distance d1 = 10; → ✅ int 값이 Distance 객체로 변환됨 (암시적 변환 발생).
- 그러나, 개발자가 명확하게 Distance d1(10);로 작성하지 않았음에도 객체가 생성됨.
- 이로 인해 의도하지 않은 변환이 발생할 위험이 있음.
📌 2. explicit 키워드를 사용하여 변환 방지
🔹 (1) explicit 키워드란?
- 암시적 변환을 막고, 명시적 변환만 허용하는 키워드.
- 생성자 앞에 explicit을 붙이면, 암시적 변환이 금지되고, 명시적 변환만 가능해짐.
💡 예제: explicit 키워드 적용
#include <iostream>
class Distance {
private:
int meters;
public:
explicit Distance(int m) { // ✅ explicit 사용 → 암시적 변환 방지
meters = m;
std::cout << "Distance 객체 생성됨! (" << meters << "m)" << std::endl;
}
void show() { std::cout << "거리: " << meters << "m" << std::endl; }
};
int main() {
// Distance d1 = 10; // ❌ 컴파일 오류 발생! (암시적 변환 금지됨)
Distance d2(10); // ✅ 명시적 변환은 가능
d2.show();
return 0;
}
🔹 출력 결과
Distance 객체 생성됨! (10m)
거리: 10m
🔹 컴파일 오류 메시지 (만약 Distance d1 = 10;을 실행했다면)
error: conversion from ‘int’ to non-scalar type ‘Distance’ requested
💡 설명
- explicit 키워드를 추가하면 Distance d1 = 10; 같은 암시적 변환이 금지됨.
- 대신, 명시적으로 Distance d2(10);와 같이 작성해야만 객체를 생성할 수 있음.
📌 3. 예제 및 활용법
🔹 (1) 단일 인자 생성자에서 explicit 적용 여부에 따른 차이점
- 단일 인자 생성자는 암시적 변환이 가능하므로, explicit 키워드를 사용하면 안전성이 증가함.
- 암시적 변환을 허용해야 하는 경우, explicit을 제거할 수 있음.
💡 예제: explicit 유무에 따른 차이점
#include <iostream>
class A {
public:
explicit A(int x) { std::cout << "A 생성자 호출! 값: " << x << std::endl; }
};
class B {
public:
B(int x) { std::cout << "B 생성자 호출! 값: " << x << std::endl; }
};
int main() {
// A a1 = 5; // ❌ 컴파일 오류 (explicit이 적용되어 암시적 변환 불가)
A a2(5); // ✅ 명시적 변환만 가능
B b1 = 5; // ✅ 암시적 변환 허용됨 (explicit 없음)
B b2(5); // ✅ 명시적 변환 가능
return 0;
}
🔹 출력 결과
A 생성자 호출! 값: 5
B 생성자 호출! 값: 5
B 생성자 호출! 값: 5
💡 설명
- A 클래스는 explicit 생성자를 사용했으므로 암시적 변환이 금지됨 (A a1 = 5; 컴파일 오류).
- B 클래스는 explicit이 없으므로 암시적 변환(B b1 = 5;)이 가능.
🔹 (2) explicit을 사용해야 하는 경우
상황 | explicit 필요 여부 |
암시적 변환이 원치 않는 경우 | ✅ explicit을 사용하여 강제 변환 방지 |
단일 인자 생성자가 여러 개 있는 경우 | ✅ explicit을 사용하여 혼란 방지 |
객체를 특정 연산에서만 명시적으로 생성해야 하는 경우 | ✅ explicit을 활용하여 제어 |
💡 예제: explicit을 사용해야 하는 경우
class Time {
public:
explicit Time(int minutes) { // ✅ 암시적 변환 방지
std::cout << "시간: " << minutes << "분" << std::endl;
}
};
int main() {
// Time t = 30; // ❌ 오류! (암시적 변환 금지)
Time t(30); // ✅ 명시적 변환 가능
}
🔹 출력 결과
시간: 30분
📌 4. 정리
개념 | 설명 |
암시적 변환(Implicit Conversion) | 단일 인자 생성자가 있을 경우, 해당 타입의 값이 객체로 변환될 수 있음 |
암시적 변환의 문제점 | 의도하지 않은 객체 변환 발생 가능 (Class obj = 10;) |
explicit 키워드의 역할 | 암시적 변환을 방지하고, 명시적 변환만 허용 |
explicit 적용 시 특징 | Class obj(10);만 허용, Class obj = 10;은 허용되지 않음 |
사용해야 하는 경우 | 변환이 명확해야 하거나, 불필요한 자동 변환을 방지할 때 |
'프로그래밍 언어 > C++' 카테고리의 다른 글
C++ 초급 - 9. 템플릿 기초 (2 - 클래스 템플릿 (Class Template)) (0) | 2025.02.22 |
---|---|
C++ 초급 - 9. 템플릿 기초 (1 - 함수 템플릿 (Function Template)) (0) | 2025.02.22 |
C++ 초급 - 8. 객체지향 프로그래밍 (5 - C++11의 override와 final) (0) | 2025.02.22 |
C++ 초급 - 8. 객체지향 프로그래밍 (4 - 인터페이스 개념 (Interface)) (0) | 2025.02.22 |
C++ 초급 - 8. 객체지향 프로그래밍 (3 - 순수 가상 함수 (= 0)) (0) | 2025.02.22 |