Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++ explicit 키워드의 역할과 사용법 완벽 가이드

이 글에서는 C++에서 explicit 키워드가 어떤 영향을 미치는지 자세히 알아보겠습니다. 본격적인 설명에 앞서, 먼저 예제 코드를 살펴보고 출력 결과를 예측해 보겠습니다.

예제 1: explicit 키워드 없이 작성한 코드

#include <iostream>
using namespace std;
class Point {
    private:
        double x, y;
    public:
        Point(double a = 0.0, double b = 0.0) : x(a), y(b) {
            //생성자
        }
        bool operator==(Point p2) {
            if(p2.x == this->x && p2.y == this->y)
            return true;
            return false;
        }
};
int main() {
    Point p(5, 0);
    if(p == 5)
        cout << "They are same";
    else
        cout << "They are not same";
}

출력 결과

They are same

왜 이런 결과가 나올까요?

위 코드는 정상적으로 컴파일되어 실행됩니다. 그 이유는 인수를 하나만으로도 호출할 수 있는 생성자가 존재하기 때문입니다. 이러한 생성자는 자동으로 변환 생성자(conversion constructor)로 동작하여, p == 5 비교 시 정수 5가 암시적으로 Point 객체로 변환됩니다.

하지만 이런 암시적 형변환은 개발자의 의도와 다르게 동작할 수 있으며, 신뢰할 수 없는 결과를 초래할 가능성이 있습니다. 따라서 대부분의 경우 이러한 변환을 제한하는 것이 좋습니다.

예제 2: explicit 키워드 적용

암시적 변환을 막으려면 생성자 앞에 explicit 한정자를 붙이면 됩니다. 이 경우 컴파일러는 더 이상 자동 형변환을 수행하지 않습니다.

#include <iostream>
using namespace std;
class Point {
    private:
        double x, y;
    public:
        explicit Point(double a = 0.0, double b = 0.0) : x(a), y(b) {
            //생성자
        }
        bool operator==(Point p2) {
            if(p2.x == this->x && p2.y == this->y)
            return true;
            return false;
        }
};
int main() {
    Point p(5, 0);
    if(p == 5)
        cout << "They are same";
    else
        cout << "They are not same";
}

출력 결과

[Error] no match for 'operator==' (operand types are 'Point' and 'int')
[Note] candidates are:
[Note] bool Point::operator==(Point)

explicit 키워드를 사용하면 위와 같이 컴파일 오류가 발생합니다. 정수형 값이 더 이상 Point 객체로 암시적으로 변환되지 않기 때문에, operator==에 대한 유효한 연산자 매칭을 찾을 수 없게 됩니다.

예제 3: 명시적 캐스팅으로 변환하기

다만 explicit 키워드를 사용하더라도, 개발자가 의도적으로 명시적 캐스팅(explicit casting)을 수행하면 여전히 값을 Point 타입으로 변환할 수 있습니다.

#include <iostream>
using namespace std;
class Point {
    private:
        double x, y;
    public:
        explicit Point(double a = 0.0, double b = 0.0) : x(a), y(b) {
            //생성자
        }
        bool operator==(Point p2) {
            if(p2.x == this->x && p2.y == this->y)
            return true;
            return false;
        }
};
int main() {
    Point p(5, 0);
    if(p == (Point)5)
        cout << "They are same";
    else
        cout << "They are not same";
}

출력 결과

They are same

정리

  • 인수 하나로 호출 가능한 생성자는 기본적으로 암시적 변환 생성자로 동작합니다.
  • explicit 키워드를 붙이면 암시적 형변환이 차단되어, 의도하지 않은 객체 변환으로 인한 버그를 예방할 수 있습니다.
  • 필요한 경우에는 명시적 캐스팅 (Point)5 또는 C++11 스타일의 static_cast<Point>(5)를 통해 변환할 수 있습니다.
  • 따라서 단일 인수 생성자에는 가능한 한 explicit를 선언하는 것이 안전한 코딩 습관입니다.