나는 순간에 두 가지 문제를 볼 수 있습니다
1 :
:
바와 같이 코멘트에 Brian 지적
가장 성가신 구문 분석을,이 라인은 실제로 함수의 프로토 타입입니다
ChildException exc();
ChildException
exc
은 기본 생성자를 호출하여 초기화되거나 012라는 함수로 읽을 수 있습니다.은 ChildException
을 반환합니다. 정확한 이유는 확실하지 않지만 C++ 표준은이 상황에서 후자로 읽히도록 지시합니다.
괄호를 제거 : 당신은 그냥 기본 생성자를 호출하는 경우, 당신은 단지 괄호없이 쓸 수
는이 문제를 해결하는 방법은 세 가지가 있습니다. 그러나 이것은 항상 옵션이되는 것은 아니지만, 함수 호출로 얻은 값으로 직접 초기화를 사용하려고 할 때 가장 귀찮은 구문을 파헤쳐 버릴 수도 있습니다.
ChildException exc;
// Most vexing parse:
ChildException ce;
ChildException ce2(ce);
// This is safe, it can't be read as a function prototype.
ChildException ce3(ChildException());
// This will be parsed as a function with:
// Return type: ChildException
// Parameter: Function pointer of type "ChildException (*)()".
를 사용하여 복사 초기화 : 당신은 컴파일러가 복사 생략을 통해 멀리 최적화 할당 구문, 그것을 초기화 할 수 있습니다.
ChildException exc = ChildException();
이 작동하지만, 불필요하게 못생긴 외모, 당신은 이 생략 복사 수행 할 수있는 컴파일러가 발생하면 덜 효율적되는 위험을 실행합니다.
uniform initialisation 사용 : C++ 11부터 uniform initialisation *을 지원하는 컴파일러를 사용할 때 괄호 대신 중괄호를 사용하여 생성자 호출을 지정할 수 있습니다. 질문의 태그를 고려해 볼 때이 방법을 권장합니다.
ChildException exc{};
는 * [세 "큰"컴파일러 중, 균일 한 초기화는 연타 3.1에서 지원되거나 이후, GCC 4.6 이상 및 Visual Studio 2013 이상. GCC는 4.4 버전을 지원했지만 Visual Studio는 2012 CTP 버전을 지원했지만 이전 버전에서는 일부 상황에서 어려움이있었습니다. 나는 Clang의 초기 버전에 문제가 있는지 확실하지 않습니다.]
2 : 더 구체적으로
//std::cout << static_cast<std::exception> (exc).what() << std::endl;
//std::cout << static_cast<std::runtime_error> (exc).what() << std::endl;
또는, : 다이아몬드 문제
나는 당신이 문제가있는 코드가 두 주석 처리 된 줄이라고 가정 할 문제는 두 번째 줄이 제대로 작동하는 동안 해당 줄 중 첫 번째 줄에 "모호한 변환"오류가 발생한다는 것입니다. 이는 ChildException
이 실제로는 두 개의std::exception
개의 기본 클래스를 가지며 각 클래스는 서로 분리되어 있기 때문입니다. 당신이 경우 귀하의 Exception
사실상 std::exception
에서 상속 동안, std::runtime_error
하지 않는 것을,
class ChildException size(28):
+---
| +--- (base class Exception)
0 | | {vbptr}
| +---
+---
+--- (virtual base runtime_error)
| +--- (base class exception)
4 | | {vfptr}
8 | | _Mywhat
12 | | _Mydofree
| | <alignment member> (size=3)
| +---
+---
+--- (virtual base exception)
16 | {vfptr}
20 | _Mywhat
24 | _Mydofree
| <alignment member> (size=3)
+---
참고 : 클래스의 레이아웃은 특별히 이런 일을 보인다. 이로 인해 std::exception
의 기본 문자가 Exception
의 std::exception
베이스와 별개이므로 ChildException
을 std::exception
으로 변환하려는 시도는 모호합니다. ChildException::Exception::exception
기본 또는 ChildException::runtime_error::exception
기본을 참조 할 수 있습니다. 가능한 경우 예외 클래스를 리팩터링하여 각 클래스가 하나의 std
예외 클래스에서 상속받을 수 있도록 제안합니다. 때문에 다이아몬드 문제로 인한 문제로
// Cast into std::exception through the base classes:
std::cout << "As Exception: "
<< static_cast<std::exception>(static_cast<Exception>(exc)).what()
<< std::endl;
std::cout << "As runtime_error: "
<< static_cast<std::exception>(static_cast<std::runtime_error>(exc)).what()
<< std::endl;
이 권장되지 않지만, 필요한 경우 사용할 수 있습니다 : 이것이 가능하지 않다면, 당신은 기본 클래스 중 하나를 통해 캐스팅 할 수 있습니다. 이는 각각 std::exception
에 액세스하기 때문입니다. 첫 번째 클래스는 클래스 레이아웃 끝에 virtual
에 액세스하고 두 번째 클래스는 std::runtime_error
내부에 액세스합니다.
* 코드는 컴파일되지만 작동하지 않습니다. * - 작동하지 않음으로써 무엇을 의미합니까? –
'exc'는'ChildException'을 반환하는 함수로 선언되었습니다. – Brian
그냥 알 수 없지만 생성자'std :: exception (const char * const &)'는 비표준 확장자입니다. Visual Studio에서는이 기능을 사용하지만 다른 주요 컴파일러가 있는지는 잘 모르겠습니다. 앞으로 다른 컴파일러를 사용한다면 당신을 물으려 고 돌아올 수 있기 때문에 나는 그것을 지적 할 것입니다. –