왜 캐스팅을 피해야합니까? [닫은]


97

나는 일반적으로 형변환 유형을 가능한 한 많이 피합니다. 코딩 관행이 좋지 않고 성능 저하를 초래할 수 있다는 인상을 받기 때문입니다.

하지만 누군가 나에게 그 이유를 정확히 설명 해달라고하면 나는 아마도 헤드 라이트에있는 사슴처럼 볼 것입니다.

그렇다면 왜 / 언제 캐스팅이 나쁜가요?

Java, C #, C ++에 대해 일반적입니까? 아니면 모든 런타임 환경에서 자체 용어로 처리합니까?

모든 언어에 대한 세부 사항은 환영합니다. 예를 들어 C ++에서 왜 나쁜가요?


3
이 인상은 어디서 얻었습니까?
Oded

8
책을 읽지 않았거나 "CASTING SOOOO GOOOOD !!!"라는 프로그래머를 만난 적이 없기 때문에 이런 인상을 받았습니다.
LoudNPossiblyWrong 2010

15
C ++에 대한 대답은 C #에 대한 대답과 필연적으로 다릅니다. 이것은 매우 언어별로 다릅니다. 지금까지의 답변은 특정 언어에 대한이 질문에 대한 답변이며 어떤 경우에는 어떤 언어에 대해 말하고 있는지 설명하지 않습니다.
James McNellis 2010

2
나쁜 것은 상대적인 용어입니다. 캐스팅을 피하는 것이 최선의 방법이지만 때로는 프로그래머가해야 할 일을 프로그래머가해야합니다. (특히 1.4 용으로 작성된 라이브러리를 사용하는 Java 1.5+ 프로그램을 작성하는 경우) "왜 캐스팅을 피해야합니까?"라는 질문의 이름을 바꿀 수 있습니다.
Mike Miller

2
대단한 질문입니다 .... 평판이 1 만 이하인 사용자 5 명에 의해 마감되었습니다 !! 분명히 새로운 힘의 과도한 사용. 재 개설에 투표했습니다.
reach4thelasers

답변:


141

여기에 세 가지 언어로 태그를 달았는데 세 언어의 대답은 정말 다릅니다. C ++에 대한 논의는 C 캐스트에 대한 논의도 의미하며, 네 번째 답을 제공합니다.

명시 적으로 언급하지 않은 것이므로 C로 시작하겠습니다. C 캐스트에는 많은 문제가 있습니다. 하나는 그들이 다양한 일을 할 수 있다는 것입니다. 어떤 경우에는 캐스트가 컴파일러에게 (본질적으로) "종료, 내가하는 일을 알고 있습니다"라고 말하는 것 이상을 수행하지 않습니다. 즉, 문제를 일으킬 수있는 변환을 수행 할 때도 컴파일러가 잠재적 인 문제에 대해 경고하지 않습니다. 예를 들어 char a=(char)123456;. 정의 된이 구현의 정확한 결과 (크기 및 서명 정도에 따라 다름)char), 다소 이상한 상황을 제외하고는 아마도 유용하지 않을 것입니다. C 캐스트는 또한 컴파일 타임에만 발생하는 것인지 (즉, 컴파일러에게 일부 데이터를 해석 / 처리하는 방법을 알려주는 것임) 런타임에 발생하는 것 (예 : double에서 실제 변환)인지 여부에 따라 다릅니다. 긴).

C ++는 여러 "새로운"캐스트 연산자를 추가하여 적어도 어느 정도이를 처리하려고합니다. 각 연산자는 C 캐스트 기능의 하위 집합으로 만 제한됩니다. 당신이 경우 -이 (예를 들어) 실수로 당신이 정말로 의도하지 않은 변환 할 더 어렵게 단지 당신이 사용할 수있는 객체에 const와 멀리 캐스팅 의도을 const_cast하고 있는지 것일 이 영향을 줄 수있는 일이 있는지 여부입니다 객체는 const, volatile또는 아닙니다. 반대로,이 static_cast객체인지 여부에 영향을 할 수 없습니다 const또는volatile. 요컨대, 대부분의 동일한 유형의 기능을 가지고 있지만 한 캐스트가 일반적으로 한 가지 유형의 변환 만 수행 할 수 있도록 분류되어 단일 C 스타일 캐스트가 한 번의 작업으로 2 ~ 3 개의 변환을 수행 할 수 있습니다. 주된 예외는 적어도 일부 경우 에 a 대신 a 를 사용할 있으며 으로 작성 되었음에도 불구하고 실제로 . 예를 들어, 클래스 계층을 위 또는 아래로 이동하는 데 사용할 수 있지만 계층 구조를 "위"로 캐스트하는 것은 항상 안전하므로 정적으로 수행 할 수 있지만 계층 구조를 "아래로"캐스트하는 것은 반드시 안전하지 않으므로 안전하지 않습니다. 동적으로 수행됩니다.dynamic_caststatic_castdynamic_caststatic_castdynamic_cast

Java와 C #은 서로 훨씬 더 유사합니다. 특히, 둘 다 캐스팅은 (가상?) 항상 런타임 작업입니다. C ++ 캐스트 연산자의 경우 일반적으로 dynamic_cast실제로 수행 된 작업의 관점 에서 a 에 가장 가깝습니다. 즉, 개체를 특정 대상 유형으로 캐스팅하려고 할 때 컴파일러는 해당 변환이 허용되는지 여부를 확인하기 위해 런타임 검사를 삽입합니다. , 그렇지 않은 경우 예외를 throw합니다. 정확한 세부 사항 (예 : "불량 캐스트"예외에 사용 된 이름)은 다양하지만 기본 원칙은 거의 유사합니다 (메모리가 제공되는 경우 Java는 intC에 훨씬 더 가까운 몇 가지 비 객체 유형에 캐스트를 적용합니다. 캐스트-그러나 이러한 유형은 1) 확실히 기억하지 못하며 2) 사실이더라도 어쨌든별로 중요하지 않습니다).

좀 더 일반적으로 살펴보면 상황은 매우 간단합니다 (적어도 IMO). 캐스트 (분명히 충분히)는 특정 유형에서 다른 유형으로 무언가를 변환하고 있음을 의미합니다. 그렇게하면 "왜?"라는 질문이 제기됩니다. 정말로 무언가가 특정 유형이되기를 원한다면, 시작하는 유형으로 정의하지 않은 이유는 무엇입니까? 그것은 그러한 변환을 할 이유가 전혀 없다는 것을 말하는 것이 아니라, 그것이 일어날 때마다 올바른 유형이 전체에 사용되도록 코드를 재 설계 할 수 있는지에 대한 질문을해야합니다. 겉보기에 무해한 변환 (예 : 정수와 부동 소수점 사이)조차도 일반적인 것보다 훨씬 더 면밀히 조사해야합니다. 그들의 모습 에도 불구하고유사성, 정수는 "계산 된"유형의 경우 실제로 사용되어야하며 "측정 된"유형의 경우 부동 소수점을 사용해야합니다. 구별을 무시하는 것은 "평균적인 미국 가정에는 1.8 명의 자녀가있다"와 같은 말도 안되는 말로 이어진다. 우리 모두 그 일이 어떻게 일어나는지 알 수 있지만 사실은 1.8 명의 자녀가있는 가족이 없다는 것 입니다. 1 개 또는 2 개 또는 그 이상일 수 있지만 1.8 개는 없습니다.


10
여기에서 '주의 기간에 의한 죽음'을 겪고있는 것 같습니다. 이것은 좋은 대답입니다.
Steve Townsend

2
강력한 대답이지만 "모르는"부분 중 일부를 강화하여 포괄적으로 만들 수 있습니다. @ Dragontamer5788 좋은 대답이지만 포괄적이지 않습니다.
M2tM 2010

5
전체 어린이 1 명과 다리가없는 어린이 1 명은 1.8 명입니다. 그러나 아주 좋은 대답은 적지 않습니다. :)
오즈.

1
자녀 가 없는 부부를 배제함으로써 전혀 방해받지 않는 아주 좋은 대답 입니다.

@Roger : 제외하지 않고 그냥 무시합니다.
Jerry Coffin

48

여기에 좋은 답변이 많이 있습니다. 다음은 내가 보는 방식입니다 (C # 관점에서).

캐스팅은 일반적으로 다음 두 가지 중 하나를 의미합니다.

  • 이 표현식의 런타임 유형을 알고 있지만 컴파일러는이를 모릅니다. 컴파일러는 런타임에이 표현식에 해당하는 객체가 실제로이 유형이 될 것이라고 말하고 있습니다. 현재로서는이 표현이이 유형의 것으로 취급된다는 것을 알고 있습니다. 객체가 주어진 유형일 것이라고 가정하는 코드를 생성하거나, 내가 틀렸다면 예외를 던집니다.

  • 컴파일러와 개발자 모두 식의 런타임 유형을 알고 있습니다. 이 표현식이 런타임에 가질 값과 연관된 다른 유형의 다른 값이 있습니다. 주어진 유형의 값에서 원하는 유형의 값을 생성하는 코드를 생성합니다. 그렇게 할 수 없다면 예외를 던지십시오.

그것들은 반대 라는 점에 유의하십시오 . 두 종류의 캐스트가 있습니다! 현실 에 대한 힌트 를 컴파일러에 제공하는 캐스트가 있습니다.이 유형의 객체는 실제로 Customer 유형입니다. 컴파일러에게 한 유형에서 다른 유형으로 매핑수행하도록 지시 하는 캐스트가 있습니다 . 이 double에 해당하는 int가 필요합니다.

두 종류의 캐스트는 모두 적신호입니다. 첫 번째 유형의 캐스트는 "왜 개발자가 컴파일러가 모르는 것을 아는 것이 정확히 무엇입니까?"라는 질문을 제기합니다. 그런 상황에 처해 있다면 일반적으로 컴파일러 실제로 처리 할 수 있도록 프로그램을 변경하는 것이 좋습니다 . 그러면 캐스트가 필요하지 않습니다. 분석은 컴파일 타임에 수행됩니다.

두 번째 유형의 캐스트는 "처음에 대상 데이터 유형에서 작업이 수행되지 않는 이유는 무엇입니까?"라는 질문을 제기합니다. int에서 결과가 필요하다면 왜 처음에 더블을 들고 있습니까? int를 들고 있어야하지 않습니까?

여기에 몇 가지 추가 생각 :

http://blogs.msdn.com/b/ericlippert/archive/tags/cast+operator/


2
나는 그것들이 본질적으로 위험 신호라고 생각하지 않습니다. Foo에서 상속 하는 객체가 Bar있고이를에 저장 List<Bar>하면 Foo되돌리려 면 캐스트가 필요합니다 . 아마도 아키텍처 수준의 문제를 나타내지 만 ( Bars 대신 s를 저장하는 이유는 Foo무엇입니까?) 반드시 그런 것은 아닙니다. 그 경우에, Foo도에 유효한 캐스트를 가지고 int, 그것은 또한 다른 의견을 다루는 : 당신은 저장하고 Foo, 아닌를 int,이 있기 때문에 int항상 적합하지 않습니다.
Mike Caron

6
@Mike Caron-에릭에게 대답 할 수는 없지만, 나에게 붉은 깃발은 "이것이 잘못된 것"이 아니라 "생각할만한 것"을 의미합니다. 그리고 a Foo를 저장하는 데 문제가 List<Bar>없지만 캐스트 시점 Foo에서 Bar. 즉, 가상 메서드에서 제공하는 기본 제공 다형성 이외의 메커니즘을 통해 하위 유형에 대한 다른 동작이 수행되고 있습니다. 그게 올바른 해결책 일 수도 있지만 더 자주 위험 신호입니다.
Jeffrey L Whitledge

14
과연. 동물 목록에서 물건을 꺼내고 나중에 컴파일러에게 말해야한다면, 아, 그런데 첫 번째는 호랑이, 두 번째는 사자, 세 번째는 곰이라면 List <Animal>이 아닌 Tuple <Lion, Tiger, Bear>를 사용해야합니다.
Eric Lippert

5
동의하지만 Tuple<X,Y,...>튜플에 대한 더 나은 구문 지원 없이는 C #에서 널리 사용되지 않을 것이라고 생각합니다 . 이것은 언어가 사람들을 "성공의 구덩이"로 밀어 붙이는 더 나은 일을 할 수있는 곳입니다.
kvb 2015

4
@kvb : 동의합니다. C # 4에 튜플 구문을 채택하는 것을 고려했지만 예산에 맞지 않았습니다. 아마도 C # 5에서; 우리는 아직 전체 기능 세트를 해결하지 못했습니다. 비동기를 위해 CTP를 함께 가져 오는 데 너무 바쁩니다. 또는 가상의 미래 버전 일 수도 있습니다.
Eric Lippert

36

캐스팅 오류는 항상 Java에서 런타임 오류로보고됩니다. 제네릭 또는 템플릿을 사용하면 이러한 오류가 컴파일 타임 오류로 바뀌므로 실수를 저지른 경우 훨씬 쉽게 감지 할 수 있습니다.

위에서 말했듯이. 모든 캐스팅이 나쁘다는 것은 아닙니다. 그러나 그것을 피할 수 있다면 그렇게하는 것이 최선입니다.


4
이것은 모든 캐스팅이 "나쁨"이라고 가정합니다. 그러나 이것은 전적으로 사실이 아닙니다. 예를 들어 암시 적 및 명시 적 캐스트 지원이 모두 포함 된 C #을 사용합니다. 문제는 (우연히) 정보 또는 형식 안전성을 제거하는 캐스트가 수행 될 때 발생합니다 (언어에 따라 다름).

5
실제로 이것은 C ++에서 완전히 잘못되었습니다. 이 정보를 대상으로하는 언어를 포함하도록 편집해야 할 수도 있습니다.
Steve Townsend

@Erick-그럴 것입니다.하지만 Java에 대한 첫 번째 사항이나 정보가 정확한지 확인하기에 충분한 C # 세부 정보를 모릅니다.
Steve Townsend

죄송합니다. 저는 Java 사용자이므로 C ++ 지식이 충분히 제한되어 있습니다. 모호하게 의도 된 "템플릿"이라는 단어를 편집 할 수 있습니다.
Mike Miller

별로. 일부 캐스트 오류는 일반적인 오류뿐만 아니라 Java 컴파일러에 의해 포착됩니다. (String) 0을 고려하십시오.
Marquis of Lorne 2011

18

캐스팅은 본질적으로 나쁘지 않으며, 실제로는 전혀 수행해서는 안되거나 더 우아하게 수행되어야하는 것을 달성하기위한 수단으로 종종 오용되는 것입니다.

그것이 보편적으로 나쁘다면 언어는 그것을 지원하지 않을 것입니다. 다른 언어 기능과 마찬가지로 그 자리가 있습니다.

제 조언은 귀하의 기본 언어에 초점을 맞추고 모든 캐스트 및 관련 모범 사례를 이해하는 것입니다. 그것은 다른 언어로의 여행을 알려줄 것입니다.

관련 C # 문서는 여기에 있습니다 .

이전 SO 질문에서 C ++ 옵션에 대한 훌륭한 요약이 여기에 있습니다 .


9

여기서는 주로 C ++에 대해 말하고 있지만 대부분은 Java 및 C #에도 적용됩니다.

C ++는 정적으로 형식화 된 언어 입니다. 언어가 허용하는 약간의 여유가 있지만 (가상 함수, 암시 적 변환) 기본적으로 컴파일러는 컴파일 타임에 모든 개체의 유형을 알고 있습니다. 이러한 언어를 사용하는 이유 는 컴파일 타임에 오류발생할 수 있기 때문 입니다. 컴파일러의 유형을 알고있는 경우 ab, 당신이 할 때 그것은 컴파일 시간에 당신을 잡을 것입니다 a=b경우 a복잡한 숫자와 b문자열입니다.

당신이 명시 적 캐스팅을 할 때마다 당신이 생각하기 때문에 당신이 닥쳐 컴파일러에게 당신이 더 잘 알고 . 틀린 경우 일반적으로 런타임 에만 알 수 있습니다 . 그리고 런타임에 알아내는 문제는 이것이 고객의 것일 수 있다는 것입니다.


5

Java, C # 및 C ++는 강력한 유형의 언어이지만 강력한 유형의 언어는 융통성이 없다고 볼 수 있지만 컴파일 타임에 유형 검사를 수행하는 이점이 있으며 특정 작업에 대해 잘못된 유형을 사용하여 발생하는 런타임 오류로부터 사용자를 보호합니다.

기본적으로 두 가지 종류의 캐스트가 있습니다. 하나는 더 일반적인 유형에 대한 캐스트 또는 다른 유형에 대한 캐스트 (더 구체적)입니다. 보다 일반적인 유형으로 캐스팅하면 (부모 유형으로 캐스팅) 컴파일 시간 검사가 그대로 유지됩니다. 그러나 다른 유형 (더 구체적인 유형)으로 캐스팅하면 컴파일 시간 유형 검사가 비활성화되고 런타임 검사로 컴파일러로 대체됩니다. 이것은 컴파일 된 코드가 올바르게 실행될 것이라는 확신이 적다는 것을 의미합니다. 또한 추가 런타임 유형 검사로 인해 성능에 약간의 영향을 미칩니다 (Java API는 캐스트로 가득 차 있습니다!).


5
모든 캐스트가 C ++에서 유형 안전성을 "우회"하는 것은 아닙니다.
James McNellis 2010

4
모든 캐스트가 C #에서 형식 안전성을 "우회"하는 것은 아닙니다.

5
모든 캐스트가 Java에서 유형 안전성을 "우회"하는 것은 아닙니다.
Erick Robertson

11
모든 캐스팅이 캐스팅에서 유형 안전성을 "우회"하는 것은 아닙니다. 오 대기는, 그 태그는 ... 언어 참조하지 않습니다
SBI

2
C # 및 Java의 거의 모든 경우에서 시스템이 런타임 유형 검사 (무료가 아님)를 수행하기 때문에 캐스팅은 성능 저하를 가져옵니다. C ++에서는 dynamic_cast일반적으로 static_cast런타임 유형 검사를 수행해야하기 때문에 일반적으로보다 느립니다 (주의 사항 : 기본 유형으로 캐스팅하는 것이 저렴합니다 등).
Travis Gockel

4

일부 유형의 주조는 매우 안전하고 효율적이므로 주조로 간주되지 않는 경우가 많습니다.

파생 형식에서 기본 형식으로 캐스트하는 경우 일반적으로 매우 저렴하며 (종종 언어, 구현 및 기타 요인에 따라 비용이 들지 않음) 안전합니다.

int와 같은 간단한 유형에서 long int와 같은 더 넓은 유형으로 캐스트하면 다시 종종 상당히 저렴하고 (일반적으로 해당 캐스트와 동일한 유형을 할당하는 것보다 훨씬 비싸지 않음) 다시 안전합니다.

다른 유형은 더 많거나 더 비쌉니다. 대부분의 언어에서 기본 유형에서 파생 유형으로 캐스트하는 것은 저렴하지만 심각한 오류 위험이 높습니다 (C ++에서 기본에서 파생으로 static_cast하는 경우 저렴하지만 기본 값이 파생 유형이 아닌 경우 동작이 정의되지 않았고 매우 이상 할 수 있음) 또는 상대적으로 비용이 많이 들고 예외가 발생할 위험이 있습니다 (C ++의 dynamic_cast, C #의 명시 적 기반에서 파생 된 캐스트 등). Java 및 C #의 Boxing은 이것의 또 다른 예이며 훨씬 더 많은 비용 (기본 값이 처리되는 방식보다 더 많이 변경된다는 점을 고려할 때)입니다.

다른 유형의 캐스트는 정보를 잃을 수 있습니다 (긴 정수 유형에서 짧은 정수 유형으로).

이러한 위험 (예외 또는 더 심각한 오류) 및 비용의 경우는 모두 캐스팅을 피해야하는 이유입니다.

더 개념적이지만 더 중요한 이유는 캐스팅의 각 사례가 코드의 정확성에 대해 추론 할 수있는 능력이 훼손되는 경우이기 때문입니다. 각 사례는 무언가 잘못 될 수있는 또 다른 장소이며 그 방식이 시스템 전체가 잘못 될지 여부를 추론하는 복잡성을 추가 할 수 있습니다. 캐스트가 매번 안전하다고 입증하더라도 이것이 추론의 추가 부분임을 증명합니다.

마지막으로 캐스트를 많이 사용하면 개체 모델을 생성하거나 사용하거나 둘 다 고려하지 못했음을 나타낼 수 있습니다. 동일한 몇 가지 유형간에 자주 앞뒤로 캐스트하는 것은 거의 항상 유형 간의 관계를 고려하지 않는 것입니다. 익숙한. 캐스트가 나쁜 일의 신호이기 때문에 캐스트가 나쁘지는 않습니다.


2

프로그래머가 언어 기능 사용에 대한 독단적 규칙 ( "XXX를 사용하지 마십시오!", "XXX는 유해한 것으로 간주 됨"등)에 집착하는 경향이 증가하고 있습니다. 여기서 XXX는 gotos에서 protected데이터 멤버에 대한 포인터, 싱글 톤, 객체 전달에 이르기까지 다양 합니다. 값.

내 경험상 그러한 규칙을 따르는 것은 두 가지를 보장합니다. 당신은 끔찍한 프로그래머가 될 수 없으며 훌륭한 프로그래머가되지 않을 것입니다.

훨씬 더 나은 접근 방식은 이러한 포괄적 인 금지 뒤에 숨겨진 진실의 핵심을 파헤쳐 서 밝혀낸 다음 기능을 현명하게 사용하는 것입니다.이 기능 은 작업에 가장 적합한 도구 많은 상황 있다는 것을 이해하고 있습니다 .

"일반적으로 가능한 한 캐스팅 유형을 최대한 피합니다."는 이러한 과도하게 일반화 된 규칙의 좋은 예입니다. 캐스트는 많은 일반적인 상황에서 필수적입니다. 몇 가지 예 :

  1. 타사 코드와 상호 운용 할 때 (특히 해당 코드가 typedefs 로 가득 찬 경우 ). (예 : GLfloat<-> double<-> Real.)
  2. 파생에서 기본 클래스 포인터 / 참조로 캐스팅 : 이것은 매우 일반적이고 자연스러워 컴파일러가 암시 적으로 수행합니다. 명시 적으로 만들면 가독성이 높아진다면 캐스트는 뒤로가 아니라 앞으로 나아갑니다!
  3. 기본에서 파생 클래스 포인터 / 참조로 캐스팅 : 잘 설계된 코드에서도 일반적입니다. (예 : 이기종 컨테이너)
  4. 이진 직렬화 / 역 직렬화 또는 기본 제공 형식의 원시 바이트에 액세스해야하는 기타 하위 수준 코드 내부.
  5. 다른 유형을 사용하는 것이 더 자연스럽고 편리하며 읽기 쉬운 경우 언제든지. (예 : std::size_type-> int.)

분명히 캐스트를 사용하는 것이 적절 하지 않은 상황이 많이 있으며, 이것도 배우는 것이 중요합니다. 위의 답변이 그중 일부를 지적하는 데 도움이되었으므로 너무 자세히 설명하지는 않겠습니다.


1

KDeveloper의 답변 에 대해 자세히 설명하기 위해 본질적으로 형식이 안전하지 않습니다. 캐스팅을 사용하면 캐스팅 및 캐스팅 대상이 일치한다는 보장이 없으며, 이러한 경우 런타임 예외가 발생하며 이는 항상 나쁜 일입니다.

C #과 관련하여 C #에는 isas연산자가 포함되어 있기 때문에 캐스트가 성공할지 여부를 결정할 수있는 기회가 있습니다. 따라서 작업이 성공할지 여부를 결정하고 적절하게 진행하려면 적절한 단계를 수행해야합니다.


1

C #의 경우 값 유형을 처리하는 동안 관련된 boxing / unboxing 오버 헤드로 인해 캐스팅하는 동안 더주의해야합니다.


1

누군가 이미 이것을 언급했는지 확실하지 않지만 C # 캐스팅에서는 다소 안전한 방식으로 사용할 수 있으며 종종 필요합니다. 여러 유형이 될 수있는 오브젝트를 수신한다고 가정하십시오. is키워드를 사용하여 먼저 객체가 실제로 캐스팅하려는 유형인지 확인한 다음 객체를 해당 유형으로 직접 캐스팅 할 수 있습니다. (저는 Java를 많이 사용하지 않았지만 거기에서도 매우 간단한 방법이 있다고 확신합니다.)


1

두 가지 조건이 충족되는 경우에만 개체를 ​​특정 유형으로 캐스팅합니다.

  1. 당신은 그것이 그 유형이라는 것을 알고 있습니다
  2. 컴파일러는하지 않습니다

이것은 당신이 가지고있는 모든 정보가 당신이 사용하는 타입 구조에 잘 표현되어 있지 않다는 것을 의미합니다. 구현이 의미 론적 으로 모델을 구성 해야 하므로이 경우에는 분명히 그렇지 않습니다.

이제 캐스트를 할 때 두 가지 이유가있을 수 있습니다.

  1. 유형 관계를 표현하는 데 나쁜 일을했습니다.
  2. 언어 유형 시스템은 단순히 표현할만큼 표현력이 부족합니다.

대부분의 언어에서 두 번째 상황에 자주 직면합니다. Java에서와 같은 Generics는 C ++ 템플릿 시스템에 더 많은 도움이되지만 마스터하기가 어렵고 일부 작업은 불가능하거나 노력할 가치가 없을 수 있습니다.

따라서 캐스트는 특정 언어로 특정 유형 관계를 표현하기 위해 문제를 우회하는 더러운 해킹이라고 말할 수 있습니다. 더러운 해킹은 피해야합니다. 그러나 그들 없이는 살 수 없습니다.


0

일반적으로 템플릿 (또는 제네릭)은 캐스트보다 형식이 안전합니다. 그런 점에서 캐스팅 문제는 형식 안전성이라고 말하고 싶습니다. 그러나 특히 다운 캐스팅과 관련된 또 다른 미묘한 문제는 디자인입니다. 적어도 내 관점에서 다운 캐스팅은 코드 냄새이며, 내 디자인에 문제가있을 수 있으므로 추가 조사를해야합니다. 이유는 간단합니다. 추상화를 올바르게 "얻은"경우에는 필요하지 않습니다! 그런데 좋은 질문 ...

건배!


0

간결하게 말하면 좋은 이유는 이식성 때문입니다. 같은 언어를 수용하는 다른 아키텍처는 예를 들어 다른 크기의 int를 가질 수 있습니다. 따라서 내가 ArchA에서 더 좁은 int를 가진 ArchB로 마이그레이션하면 기껏해야 이상한 동작을 볼 수 있고 최악의 경우 seg 오류가 발생할 수 있습니다.

(저는 아키텍처 독립적 인 바이트 코드와 IL을 분명히 무시하고 있습니다.)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.