변환 생성자 대 변환 연산자 : 우선 순위
여기에서 변환 연산자와 생성자에 대한 몇 가지 질문을 읽으면 '모호한'호출이있을 때 그들 사이의 상호 작용에 대해 생각하게되었습니다. 다음 코드를 고려하십시오.
class A;
class B {
public:
B(){}
B(const A&) //conversion constructor
{
cout << "called B's conversion constructor" << endl;
}
};
class A {
public:
operator B() //conversion operator
{
cout << "called A's conversion operator" << endl;
return B();
}
};
int main()
{
B b = A(); //what should be called here? apparently, A::operator B()
return 0;
}
위의 코드는 "A의 변환 연산자라고하는"을 표시합니다. 즉, 생성자가 아닌 변환 연산자가 호출됩니다. 에서 operator B()
코드 를 제거 / 주석 처리 A
하면 컴파일러가 생성자를 대신 사용하도록 기꺼이 전환합니다 (코드에 대한 다른 변경 사항 없음).
내 질문은 다음과 같습니다.
- 컴파일러는
B b = A();
모호한 호출로 간주하지 않기 때문에 여기에서 작업에 어떤 유형의 우선 순위가 있어야합니다. 이 우선 순위는 정확히 어디에 설정되어 있습니까? (C ++ 표준의 참조 / 인용을 주시면 감사하겠습니다) - 객체 지향 철학적 관점에서 볼 때 이것이 코드가 동작해야하는 방식입니까? 누가 더 방법에 대해 알고있는
A
객체가이되어야B
객체,A
또는B
? C ++에 따르면 대답은A
-이것이 사실이어야한다고 제안하는 객체 지향 연습에 어떤 것이 있습니까? 개인적으로 어느 쪽이든 말이 될 것이므로 어떻게 선택했는지 알고 싶습니다.
미리 감사드립니다
복사 초기화를 수행하고 변환 시퀀스에서 변환을 수행하는 것으로 간주되는 후보 함수는 변환 함수와 변환 생성자입니다. 이것은 귀하의 경우입니다
B(const A&)
operator B()
자, 그것이 당신이 그들을 선언하는 방법입니다. 오버로드 해결은이를 추상화하고 각 후보를 호출 인수에 해당하는 매개 변수 목록으로 변환합니다. 매개 변수는
B(const A&)
B(A&)
두 번째는 변환 함수가 멤버 함수이기 때문입니다. 는 A&
후보 멤버 함수 때 발생있어 소위 내장 객체 파라미터이다. 이제 인수에는 유형이 A
있습니다. 암시 적 개체 매개 변수를 바인딩 할 때 상수가 아닌 참조 가 rvalue에 바인딩 될 수 있습니다 . 따라서 또 다른 규칙은 매개 변수가 참조 인 두 개의 실행 가능한 함수가있을 때 가장 적은 const 자격을 가진 후보 가 승리 할 것이라고 말합니다 . 그것이 당신의 변환 함수가이기는 이유입니다. operator B
const 멤버 함수를 만들어보십시오 . 모호함을 알게 될 것입니다.
객체 지향 철학적 관점에서 볼 때 이것이 코드가 동작해야하는 방식입니까? A 객체가 B 객체, A 또는 B가되는 방법에 대해 누가 더 많이 알고 있습니까? C ++에 따르면 대답은 A입니다. 객체 지향 실습에서 이것이 사실이어야한다고 제안하는 것이 있습니까? 개인적으로 어느 쪽이든 말이 될 것이므로 어떻게 선택했는지 알고 싶습니다.
기록을 위해 변환 함수를 const 멤버 함수로 만들면 GCC가 생성자를 선택합니다 (그래서 GCC B
가 더 많은 비즈니스가 있다고 생각하는 것 같 습니까?). -pedantic
진단을 수행 하려면 현학 모드 ( )로 전환하십시오 .
스탠다드, 8.5/14
Otherwise (i.e., for the remaining copy-initialization cases), user-defined conversion sequences that can convert from the source type to the destination type or (when a conversion function is used) to a derived class thereof are enumerated as described in 13.3.1.4, and the best one is chosen through overload resolution (13.3).
And 13.3.1.4
Overload resolution is used to select the user-defined conversion to be invoked. Assuming that "cv1 T" is the type of the object being initialized, with T a class type, the candidate functions are selected as follows:
- The converting constructors (12.3.1) of T are candidate functions.
- When the type of the initializer expression is a class type "cv S", the conversion functions of S and its base classes are considered. Those that are not hidden within S and yield a type whose cv-unqualified version is the same type as T or is a derived class thereof are candidate functions. Conversion functions that return "reference to X" return lvalues of type X and are therefore considered to yield X for this process of selecting candidate functions.
In both cases, the argument list has one argument, which is the initializer expression. [Note: this argument will be compared against the first parameter of the constructors and against the implicit object parameter of the conversion functions. ]
And 13.3.3.2/3
- Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if [...] S1 and S2 are reference bindings (8.5.3), and the types to which the references refer are the same type except for top-level cv-qualifiers, and the type to which the reference initialized by S2 refers is more cv-qualified than the type to which the reference initialized by S1 refers.
It seems MSVS2008 has its own opinion about constructor selection: it calls copy constructor in B regardless of constness of A's operator. So be careful here even while standard specifies the correct behavior.
I thought MSVS just search for suitable constructor before conversions operator, but then found that it starts calling A's operator B() if you remove const word from B's constructor. Probably it has some special behavior for temporaries, because the following code still calls B's constructor:
A a;
B b = a;
참고URL : https://stackoverflow.com/questions/1384007/conversion-constructor-vs-conversion-operator-precedence
'Development Tip' 카테고리의 다른 글
"최상위 JSON 어레이"란 무엇이며 보안 위험이있는 이유는 무엇입니까? (0) | 2020.11.15 |
---|---|
Android에서 ARM EABI v7a 시스템 이미지를 사용하는 방법은 무엇입니까? (0) | 2020.11.15 |
XmlNamespaceManager가 필요한 이유는 무엇입니까? (0) | 2020.11.15 |
Laravel 5에서 모듈 식 앱을 구성하는 방법은 무엇입니까? (0) | 2020.11.15 |
자식 요소가 부모 스타일을 상속하지 못하도록하는 CSS (0) | 2020.11.15 |