C++에서 발생하는 모호한 생성자 오류(Ambiguous Constructor Error)
예시:
class MyClass {
public:
MyClass(int x);
MyClass(double y);
};
int main() {
MyClass obj(10.5); // 오류: 모호한 생성자 호출
return 0;
}
위 코드에서 MyClass
클래스에는 두 개의 생성자가 있습니다. 하나는 int
형 매개변수를 받고 다른 하나는 double
형 매개변수를 받습니다. main()
함수에서 MyClass obj(10.5)
라고 작성하면 컴파일러는 어떤 생성자를 사용해야 할지 결정할 수 없습니다.
C++17에서 도입된 Language Lawyer
C++17에서 도입된 Language Lawyer는 모호한 생성자 오류를 해결하는 데 도움이 되는 기능입니다. Language Lawyer는 컴파일러에게 특정 생성자를 사용하도록 지시하는 데 사용할 수 있습니다.
class MyClass {
public:
MyClass(int x);
MyClass(double y);
};
int main() {
MyClass obj = ::MyClass(10.5); // Language Lawyer 사용
return 0;
}
위 코드에서 ::MyClass(10.5)
라고 작성하면 Language Lawyer가 double
형 매개변수를 받는 생성자를 사용하도록 컴파일러에게 지시합니다.
MSVC와 GCC에서의 차이점
MSVC와 GCC는 모호한 생성자 오류를 다르게 처리합니다. MSVC는 일반적으로 오류를 발생시키지만 GCC는 기본 생성자를 사용할 수 있습니다.
class MyClass {
public:
MyClass();
MyClass(int x);
};
int main() {
MyClass obj(10.5); // MSVC: 오류, GCC: 기본 생성자 사용
return 0;
}
위 코드에서 MSVC는 오류를 발생시키지만 GCC는 기본 생성자를 사용하여 MyClass
객체를 생성합니다.
결론
예제 코드
#include <iostream>
class MyClass {
public:
MyClass() { std::cout << "기본 생성자 호출" << std::endl; }
MyClass(int x) { std::cout << "int 생성자 호출, x = " << x << std::endl; }
MyClass(double y) { std::cout << "double 생성자 호출, y = " << y << std::endl; }
};
int main() {
// 1. 기본 생성자 호출
MyClass obj1;
// 2. int 생성자 호출
MyClass obj2(10);
// 3. double 생성자 호출
MyClass obj3(10.5);
// 4. 모호한 생성자 호출 (오류 발생)
// MyClass obj4(10.5f); // float 값은 int와 double 생성자 모두와 일치
return 0;
}
기본 생성자 호출
int 생성자 호출, x = 10
double 생성자 호출, y = 10.5
설명:
- 위 코드는
MyClass
클래스를 선언하고 3개의 생성자를 정의합니다.- 기본 생성자
- int 형 매개변수를 받는 생성자
main()
함수에서 다양한 방법으로MyClass
객체를 생성합니다.- 기본 생성자를 사용하여 객체 생성
- float 값을 사용하여 객체 생성 (모호한 생성자 호출로 오류 발생)
참고:
- 위 코드는 C++11에서 작성되었습니다. C++17에서 도입된 Language Lawyer를 사용하면 4번째 줄의 오류를 해결할 수 있습니다.
모호한 생성자 오류를 해결하는 대체 방법
생성자 매개변수에 const 참조 사용:
class MyClass {
public:
MyClass(const int& x);
MyClass(const double& y);
};
int main() {
MyClass obj(10.5f); // const 참조 사용으로 오류 해결
return 0;
}
명시적 생성자 호출:
class MyClass {
public:
MyClass(int x);
MyClass(double y);
};
int main() {
MyClass obj = ::MyClass(10.5f); // 명시적 생성자 호출
return 0;
}
생성자를 삭제:
class MyClass {
public:
MyClass(int x);
MyClass(double y);
private:
MyClass(float); // float 생성자 삭제
};
int main() {
// MyClass obj(10.5f); // 오류: float 생성자 삭제됨
return 0;
}
사용자 정의 변환 함수 사용:
class MyClass {
public:
MyClass(int x);
MyClass(double y);
operator MyClass(float f) const {
return MyClass(static_cast<double>(f));
}
};
int main() {
MyClass obj(10.5f); // 사용자 정의 변환 함수 사용
return 0;
}
c++ c++17 language-lawyer