C ++에 리플렉션이없는 이유는 무엇입니까?


337

이것은 다소 기괴한 질문입니다. 저의 목표는 언어 설계 결정을 이해하고 C ++에서 반영 가능성을 식별하는 것입니다.

  1. 왜 C ++ 언어위원회가 언어에 대한 반영을 구현하지 않았습니까? Java와 같은 가상 머신에서 실행되지 않는 언어에서는 리플렉션이 너무 어렵습니까?

  2. C ++에 대한 리플렉션을 구현해야한다면 어떤 어려움이 있습니까?

리플렉션의 사용은 잘 알려져 있다고 생각합니다. 에디터를보다 쉽게 ​​작성할 수 있고, 프로그램 코드가 더 작아지고, 단위 테스트를 위해 모의가 생성 될 수 있습니다. 그러나 리플렉션 사용에 대해서도 언급 할 수 있다면 좋을 것입니다.

답변:


631

C ++의 리플렉션에는 몇 가지 문제가 있습니다.

  • 추가해야 할 작업이 많으며 C ++위원회는 상당히 보수적이며 획기적인 새로운 기능에 시간을 투자하지 않을 것입니다. (.NET 어셈블리와 유사한 모듈 시스템을 추가하기위한 제안이 있었으며, 그것이 좋을 것이라는 일반적인 합의가 있다고 생각하지만 현재로서는 최우선 순위가 아니며 이후까지 밀려났습니다. C ++ 0x.이 기능의 동기는 #include시스템을 제거하는 것이지만 최소한 일부 메타 데이터도 가능하게합니다.

  • 사용하지 않는 것에 대해서는 비용을 지불하지 않습니다. 이것이 C ++의 기본 디자인 철학 중 하나입니다. 메타 데이터가 필요하지 않은 경우 코드에서 메타 데이터를 가져와야하는 이유는 무엇입니까? 또한 메타 데이터를 추가하면 컴파일러가 최적화되지 않을 수 있습니다. 해당 메타 데이터가 필요하지 않은 경우 코드에서 비용을 지불해야하는 이유는 무엇입니까?

  • C ++은 컴파일 된 코드에 대해 거의 보장 하지 않습니다. 결과적인 기능이 예상되는 한 컴파일러는 좋아하는 모든 것을 할 수 있습니다. 예를 들어, 수업이 실제로 있을 필요는 없습니다 . 간단한 템플릿 코드조차도 템플릿 인스턴스화를 거의 생성하지 않기 때문에 컴파일러는 최적화하여 모든 작업을 인라인으로 수행 할 수 있습니다. C ++ 표준 라이브러리 는이 공격적인 최적화에 의존 합니다. 펑 터는 객체를 인스턴스화하고 파괴하는 오버 헤드를 최적화 할 수있는 경우에만 성능이 우수합니다. operator[]벡터에서는 전체 연산자를 인라인 할 수 있으므로 컴파일 된 코드에서 완전히 제거 할 수 있기 때문에 성능면에서 원시 배열 인덱싱과 비교할 수 있습니다. C #과 Java는 컴파일러의 출력에 대해 많은 보증을합니다. C #에서 클래스를 정의하면 해당 클래스 결과 어셈블리에 존재합니다 . 내가 그것을 사용하지 않더라도. 멤버 함수에 대한 모든 호출이 인라인 될 수있는 경우에도 마찬가지입니다. 반성이있을 수 있도록 수업이 있어야합니다. 이것의 일부는 C #을 바이트 코드로 컴파일함으로써 완화됩니다. 이는 JIT 컴파일러 초기 C # 컴파일러가 할 수 없더라도 클래스 정의와 인라인 함수를 제거하십시오. C ++에서는 하나의 컴파일러 만 있으며 효율적인 코드를 출력해야합니다. C ++ 실행 파일의 메타 데이터를 검사 할 수 있으면 정의 된 모든 클래스가 표시 될 것으로 예상됩니다. 즉, 컴파일러는 정의되지 않은 모든 클래스를 보존해야합니다.

  • 그리고 템플릿이 있습니다. C ++의 템플릿은 다른 언어의 제네릭과 다릅니다. 모든 템플릿 인스턴스화는 새로운 유형을 만듭니다 . std::vector<int>와 완전히 분리 된 클래스입니다 std::vector<float>. 그것은 전체 프로그램에서 많은 다른 유형을 추가합니다. 우리의 성찰은 무엇을보아야합니까? 템플릿 std::vector ? 그러나 런타임에 의미가없는 소스 코드 구조이기 때문에 어떻게 할 수 있습니까? 별도의 클래스 std::vector<int>와 를보아야합니다 std::vector<float>. 그리고 std::vector<int>::iterator하고 std::vector<float>::iterator, 동일에 대한const_iterator등등. 템플릿 메타 프로그래밍을 시작하면 수백 개의 템플릿을 빠르게 인스턴스화 할 수 있습니다.이 템플릿은 모두 인라인되어 컴파일러에서 다시 제거됩니다. 컴파일 타임 메타 프로그램의 일부를 제외하고는 의미가 없습니다. 이 수백 개의 클래스가 모두 반영되어야합니까? 내가 정의한 클래스가 실제로 거기에있을 것이라는 보장조차하지 않는다면, 그렇지 않으면 우리의 리플렉션은 쓸모가 없기 때문에 그들은 필요합니다 . 그리고 부수적 인 문제는 템플릿 클래스가 인스턴스화 될 때까지 존재하지 않는다는 것입니다. 를 사용하는 프로그램을 상상해보십시오 std::vector<int>. 우리 반사 시스템이 볼 수 있어야 std::vector<int>::iterator합니까? 한편으로, 당신은 확실히 그렇게 기대할 것입니다. 그것은 중요한 클래스, 그리고 그것의 관점에서 정의되어 std::vector<int>있는 않습니다메타 데이터에 존재합니다. 반면에 프로그램 이 실제로이 반복자 클래스 템플릿을 사용 하지 않으면 해당 유형이 인스턴스화되지 않았으므로 컴파일러는 클래스를 처음 생성하지 않았을 것입니다. 소스 코드에 액세스해야하므로 런타임에 작성하기에는 너무 늦습니다.

  • 마지막으로 리플렉션은 C ++ 에서처럼 C ++에서 매우 중요하지 않습니다. 그 이유는 템플릿 메타 프로그래밍입니다. 모든 것을 해결할 수는 없지만 다른 방법으로 리플렉션에 의존하는 경우 컴파일 타임에 동일한 작업을 수행하는 메타 프로그램을 작성할 수 있습니다. boost::type_traits간단한 예입니다. 타입에 대해 알고 싶 T습니까? 확인하십시오 type_traits. C #에서는 리플렉션을 사용하여 유형을 지정한 후에 낚시해야합니다. 리플렉션은 여전히 ​​일부 (유용한 메타 프로그래밍이 쉽게 대체 할 수없는 자동 생성 직렬화 코드 인 경우)에 유용하지만 C ++에는 상당한 비용이 들며 자주 필요하지는 않습니다. 다른 언어로되어 있습니다.

편집 : 의견에 대한 답변 :

cdleary : 예. 디버그 기호는 실행 파일에 사용 된 형식에 대한 메타 데이터를 저장한다는 점에서 비슷한 작업을 수행합니다. 그러나 그들은 또한 내가 설명한 문제로 고통받습니다. 릴리스 빌드 디버깅을 시도한 적이 있다면 무슨 뜻인지 알게 될 것입니다. 최종 코드에서 인라인 된 소스 코드에서 클래스를 생성 할 때 논리적으로 큰 차이가 있습니다. 유용한 것을 위해 리플렉션을 사용하려면보다 안정적이고 일관성있는 리플렉션이 필요합니다. 그대로 타입은 컴파일 할 때마다 사라지고 사라집니다. 작은 세부 사항을 변경하면 컴파일러는 응답으로 인라인 된 유형과 그렇지 않은 유형을 변경하기로 결정합니다. 언제 유용한 정보를 추출합니까? 가장 관련성이 높은 유형이 메타 데이터에 표시된다고 보장하지 않습니까? 당신이 찾고있는 타입은 마지막 빌드에 있었을 지 모르지만 이제는 사라졌습니다. 그리고 내일, 누군가는 작은 순진한 함수로 작은 순진한 변화를 체크인하여 완전히 인라인되지 않을 정도로 충분히 커지므로 다시 돌아올 것입니다. 여전히 디버그 심볼에 유용하지만 그 이상은 아닙니다. 해당 용어에 따라 클래스의 직렬화 코드를 생성하는 것을 싫어합니다. 그러나 그 이상은 아닙니다. 해당 용어에 따라 클래스의 직렬화 코드를 생성하는 것을 싫어합니다. 그러나 그 이상은 아닙니다. 해당 용어에 따라 클래스의 직렬화 코드를 생성하는 것을 싫어합니다.

Evan Teran : 물론 이러한 문제 해결 될 수 있습니다. 그러나 그것은 제 요점 1로 돌아갑니다. 많은 작업이 필요하며 C ++위원회에는 더 중요하다고 생각되는 많은 것들이 있습니다. C ++에서 제한된 반영 (및 제한적)을 얻는 이점이 다른 기능을 희생하면서 그에 집중하는 것을 정당화 할만 큼 충분히 큽니까? QT와 같은 라이브러리 및 전처리기를 통해 이미 수행 할 수있는 핵심 언어 기능을 추가 할 때 실제로 큰 이점이 있습니까? 아마도, 그러나 그러한 라이브러리가 존재하지 않는 것보다 필요성이 훨씬 덜 시급합니다. 그러나 특정 제안에 대해서는 템플릿에서 허용하지 않으면 완전히 쓸모가 없게됩니다. 예를 들어 표준 라이브러리에서 리플렉션을 사용할 수 없습니다. 어떤 종류의 반성이 있을까요?std::vector? 템플릿은 C ++ 의 부분입니다. 템플릿에서 작동하지 않는 기능은 기본적으로 쓸모가 없습니다.

그러나 당신이 옳습니다. 어떤 형태의 반사가 구현 될 수 있습니다. 그러나 그것은 언어의 주요 변화 일 것입니다. 현재 유형은 독점적으로 컴파일 타임 구성입니다. 그것들은 컴파일러의 이익을 위해 존재하며 다른 것은 없습니다. 코드가 컴파일되면 클래스 없습니다. 자신을 늘리면 함수가 여전히 존재한다고 주장 할 수 있지만 실제로 점프 어셈블러 명령이 많이 있고 스택 푸시 / 팝이 많이 있습니다. 이러한 메타 데이터를 추가 할 때는 계속 진행할 것이 없습니다.

그러나 내가 말했듯이 컴파일 모델 변경, 자체 포함 모듈 추가, 선택 유형에 대한 메타 데이터 저장, 다른 모듈이 #includes 를 망칠 필요없이 참조 할 수 있도록 제안합니다 . 좋은 출발이며, 솔직히 말해서 표준위원회가 너무 큰 변화에 대한 제안을 포기하지 않은 것에 놀랐습니다. 아마도 5-10 년 안에? :)


2
이러한 문제의 대부분이 디버그 기호로 이미 해결되지 않았습니까? (인라인 및 최적화로 인해) 성능이 좋지는 않지만 디버그 심볼이 수행하는 작업을 수행하여 반영 가능성 을 허용 할 수 있습니다.
cdleary

2
첫 번째 요점에 대한 또 다른 점은 아무도 C ++ 구현에 반영을 시도하지 않았다는 것입니다. 그것에 대한 좋은 경험이 없습니다. 위원회는 아마도 특히 export와 이후에 주도권을 갖기를 꺼려 할 것이다 vector<bool>.
David Thornley

18
C ++에 런타임 반영이 없어야한다는 데 동의합니다. 그러나 컴파일 타임 리플렉션에는 위의 문제가 거의 없으며 특정 클래스에서 원하는 경우 런타임 리플렉션을 빌드하는 데 사용할 수 있습니다. 템플릿을 통해 클래스의 n 번째 메서드와 n 번째 부모의 형식과 이름 및 기능에 액세스 할 수 있습니까? 그리고 컴파일 타임에 그러한 수를 얻습니까? CRTP 기반 자동 리플렉션을 사용 가능하게하고 사용하지 않는 것에 대해서는 아무도 지불하지 않습니다.
Yakk-Adam Nevraumont

15
세 번째 요점은 여러 측면에서 가장 중요합니다. C ++은 메모리 비용이 많이 드는 플랫폼에서 독립형 코드를 작성하는 데 적합합니다. 사용하지 않는 코드를 제거하면 프로그램이 2.50 달러가 아닌 2.00 달러의 마이크로 컨트롤러에 적합하고 코드가 1,000,000 개 단위로 진행되는 경우 해당 코드를 제거하면 500,000 달러를 절약 할 수 있습니다. 성찰이 없으면 정적 분석은 종종 도달 할 수없는 코드의 90 % 이상을 식별 할 수 있습니다. 리플렉션이 허용되는 경우 리플렉션을 통해 도달 할 수있는 모든 항목은 90 %에 도달하지 않더라도 도달 할 수있는 것으로 가정해야합니다.
supercat

2
comitee 쉽게 개선 할 수있는 일이 분명히있다, 그것은 마침내 흰색에 검은 말을하는 것입니다 typeinfoname()기능이 정의되지 않은 프로그래머가 아니라 뭔가에 입력 된 이름을 반환해야합니다. 열거 자에 대한 문자열을 제공하십시오. 이것은 실제로 직렬화 / 역 직렬화에 중요합니다. 공장 등을 만드는 데 도움이됩니다.
v.oddou

38

리플렉션을하려면 쿼리 할 수있는 곳에 메타 데이터 유형을 저장해야합니다. C ++은 네이티브 머신 코드로 컴파일하고 최적화로 인해 큰 변화를 겪기 때문에 컴파일 과정에서 응용 프로그램에 대한 높은 수준의 뷰가 거의 손실되므로 런타임에 쿼리 할 수 ​​없습니다. Java 및 .NET은 가상 머신의 이진 코드에서 매우 높은 수준의 표현을 사용하여 이러한 수준의 리플렉션을 가능하게합니다. 그러나 일부 C ++ 구현에는 제거 된 리플렉션 버전으로 간주 될 수있는 RTTI (Run Time Type Information)라는 것이 있습니다.


15
RTTI는 C ++ 표준입니다.
Daniel Earwicker

1
그러나 모든 C ++ 구현이 표준은 아닙니다. RTTI를 지원하지 않는 구현을 보았습니다.
Mehrdad Afshari

3
또한 RTTI를 지원하는 대부분의 구현은 컴파일러 옵션을 통해 끄는 기능도 지원합니다.
Michael Kohne

21

모든 언어가 다른 모든 언어의 모든 기능을 통합하려고 시도해서는 안됩니다.

C ++은 본질적으로 매우 정교한 매크로 어셈블러입니다. C #, Java, Objective-C, Smalltalk 등과 같은 고급 언어는 아닙니다.

작업마다 다른 도구를 사용하는 것이 좋습니다. 우리가 망치 만 가지고 있다면 모든 것이 손톱처럼 보일 것입니다. 스크립트 언어를 갖는 것은 일부 작업에 유용하며, 반사 형 OO 언어 (Java, Obj-C, C #)는 다른 작업 클래스에 유용합니다. 기계에 가까운 효율적인 베어 본은 또 다른 작업 클래스 (C ++, C, 어셈블러)에 유용합니다.

C ++는 어셈블러 기술을 놀라운 수준의 복잡성 관리로 확장하고 추상화를 통해 더 크고 복잡한 작업을 인간에게 훨씬 더 가능하게하는 놀라운 작업을 수행합니다. 그러나 엄격하게 높은 수준의 관점 (Lisp, Smalltalk, Java, C #)으로 문제에 접근하는 사람들에게 가장 적합한 언어 일 필요는 없습니다. 문제에 대한 솔루션을 가장 잘 구현하기 위해 이러한 기능을 갖춘 언어가 필요한 경우 우리 모두가 사용할 수 있도록 그러한 언어를 만든 사람들에게 감사하십시오!

그러나 C ++은 어떤 이유에서든 코드와 기본 시스템 작동간에 강한 상관 관계가 필요한 사람들을위한 것입니다. 효율성, 프로그래밍 장치 드라이버 또는 하위 수준 OS 서비스와의 상호 작용 등 무엇이든 C ++은 이러한 작업에 더 적합합니다.

C #, Java, Objective-C는 모두 실행을 지원하기 위해 훨씬 더 크고 풍부한 런타임 시스템이 필요합니다. 해당 런타임은 문제의 시스템에 제공되어야합니다. 소프트웨어 작동을 지원하기 위해 사전 설치되어 있습니다. 그리고 해당 플랫폼에서 작동하도록 일부 다른 언어로 사용자 정의 된 다양한 대상 시스템에 대해 해당 계층을 유지 관리해야합니다. 그리고 그 중간 계층 (호스트 OS와 코드 사이의 적응 계층)은 거의 항상 C 또는 C ++와 같은 언어로 작성되며 효율성은 1 위이며 소프트웨어와 하드웨어 사이의 정확한 상호 작용을 예측할 수 있습니다 이해하고 최대 이득으로 조작했습니다.

Smalltalk, Objective-C를 좋아하고 리플렉션, 메타 데이터, 가비지 수집 등이 포함 된 풍부한 런타임 시스템을 보유하고 있습니다. 이러한 기능을 활용하기 위해 놀라운 코드를 작성할 수 있습니다! 그러나 이는 스택의 상위 계층, 하위 계층에 있어야하는 계층이며 궁극적으로 OS 및 하드웨어에 있어야합니다. 그리고 우리는 항상 C ++ / C / Assembler라는 해당 계층을 구축하는 데 가장 적합한 언어가 필요합니다.

부록 : C ++ 11 / 14는 C ++ 기능을 계속 확장하여 더 높은 수준의 추상화 및 시스템을 지원합니다. 스레딩, 동기화, 정확한 메모리 모델,보다 정확한 추상 기계 정의를 통해 C ++ 개발자는 이러한 고급 언어 중 일부만 독점 도메인을 가졌던 기존의 여러 가지 고급 추상화를 달성 할 수 있습니다. 금속 성능 및 우수한 예측 성 (즉, 최소 런타임 서브 시스템). 아마도 리플렉션 기능은 C ++의 향후 개정판에서 선택적으로 활성화 될 것입니다. 필요한 사람들을 위해 또는 라이브러리가 그러한 런타임 서비스를 제공 할 것입니다.


다른 언어로 컴파일해야하는 언어의 런타임에 대한 요점은 Objective-C의 경우 런타임이 C로 작성되므로 Objective-C의 상위 집합이므로 사실이 아닙니다.
Richard J. Ross III

그것은 차이가없는 구별입니다. 결국 Objective-C가 사용하는 런타임 서브 시스템이 실제로 Objective-C로 작성된 것이 아니라 C로 작성된 차이점은 무엇입니까?
Mordachai

3
죄송 해요; 그러나 올바르게 링크하는 한 objective-c 프로그램을 C로 컴파일 할 수 있습니다. 실제로 여기에서했습니다 : stackoverflow.com/a/10290255/427309 . 위의 진술 전체가 허위입니다. 런타임은 C를 통해 완전히 액세스 할 수 있으며 런타임을 강력한 동적 언어로 만드는 것 중 하나입니다.
Richard J. Ross III

1
"C 런타임"은 C 표준 라이브러리의 코드를 포함하는 동적 라이브러리입니다. "C ++ 런타임"과 동일합니다. Objective-C와 같은 런타임 시스템과는 상당히 다릅니다. 또한 ... C에서 Objective-C 런타임을 기술적으로 사용할 수 있다고 가정하지만, 여전히 Objective-C 런타임을 사용하는 C 프로그램 일뿐입니다. C에서는 실제 Objective-C 프로그램을 컴파일 할 수 없습니다.
celticminstrel

2
C ++ 11 갖는 메모리 모델 + 아토을 만드는 휴대 어셈블러 등을들 수있다. 그것들은 높은 수준의 것이 아니며 이전에 C ++에서 휴대용 지원이 부족한 낮은 수준의 것입니다. 그러나 C ++의 UB 양은 잘못하면 Java와 같은 VM 기반 언어와 다르며 특정 어셈블리 언어와도 다릅니다. 예를 들어 signed-overflow는 C ++ 소스에서 완전히 UB이며 컴파일러는 x86이라고 말하더라도 컴파일러는이 사실을 기반으로 최적화 할 수 있지만 거의 모든 플랫폼에서 asm에서는 래핑됩니다. 현대 C ++은 이식 가능한 어셈블리 언어와는 거리가 멀다.
Peter Cordes

11

C ++를 둘러싼 디자인 결정을 실제로 이해하려면 Ellis와 Stroustrup 의 Annotated C ++ Reference Manual 사본을 찾으십시오 . 최신 표준은 최신이 아니지만 원래 표준을 통과하여 작동 방식과 빈도, 방법을 설명합니다.


6
스트로브 스트 룹에 의해 또한 설계 및 C의 진화 ++
제임스 Hopkin

9

리플렉션이있는 언어에 대한 리플렉션은 리플렉션을 가능하게하기 위해 컴파일러가 객체 코드에 남길 소스 코드의 양과 리플렉션 된 정보를 해석하는 데 사용할 수있는 분석 메커니즘의 정도에 관한 것입니다. 컴파일러가 모든 소스 코드를 유지하지 않으면 소스 코드에 대한 사용 가능한 사실을 분석하는 기능이 제한됩니다.

당신이 반사하지 않는 때문에 C ++ 컴파일러는 (RTTI를 무시 아니라) 주위에 아무것도 유지하지 않습니다 에서 언어를. (Java 및 C # 컴파일러는 클래스, 메소드 이름 및 리턴 유형 만 유지하므로 약간의 리플렉션 데이터를 얻을 수 있지만 표현식 또는 프로그램 구조를 검사 할 수 없으며 "반사 가능"언어에서도 마찬가지입니다. 얻을 수있는 정보는 매우 드물고 결과적으로 많은 분석을 수행 할 수 없습니다.

그러나 언어를 벗어나서 완전한 반영 기능을 얻을 수 있습니다. C의 리플렉션에 대한 다른 스택 오버플로 토론에 대한 답변 이 이에 대해 설명합니다.


7

리플렉션은 이전에 C ++에서 구현 될 수 있었고 구현되었습니다.

이 언어는 기본적으로 언어에 의해 설정되어서는 안되는 많은 비용 (메모리 및 속도)이 있기 때문에 기본 c ++ 기능이 아닙니다. 언어는 "기본적으로 최대 성능"입니다.

당신이 필요로하지 않는 것에 대해 비용을 지불해서는 안되고, 당신이 말한 것처럼 다른 어플리케이션보다 편집기에서 더 많이 필요로하므로, 필요한 경우에만 구현해야하며 모든 코드에 "강제"되지 않아야합니다 ( 편집기 나 다른 유사한 응용 프로그램에서 작업 할 모든 데이터를 반영 할 필요는 없습니다.


3
고객 / 경쟁 업체가 코드를 볼 수 있도록 심볼을 제공하지 않습니다. 이는 종종 나쁜 것으로 간주됩니다.
gbjbaanb

당신이 맞아요, 코드 노출 문제에 대해서는 생각조차하지 않았습니다. :)
Klaim

6

C ++에 리플렉션이없는 이유는 클래스 유형에있는 멤버, 멤버에 대한 정보, 함수 및 모든 것에 대한 기호 정보를 컴파일러가 오브젝트 파일에 추가해야하기 때문입니다. 선언에 의해 전달 된 정보는 해당 객체 파일 (모듈)에서 읽히므로 기본적으로 포함 파일을 사용할 수 없게됩니다. C ++에서 유형 정의는 해당 헤더를 모두 포함하여 프로그램에서 여러 번 발생할 수 있으므로 (모든 정의가 동일하다면) 해당 유형에 대한 정보를 어디에 둘 것인지를 결정해야합니다. 여기 합병증. 수십 개의 클래스 템플릿 인스턴스화를 최적화 할 수있는 C ++ 컴파일러가 수행하는 적극적인 최적화는 또 다른 장점입니다. 가능하지만 C ++이 C와 호환되므로


1
컴파일러의 적극적인 최적화가 어떻게 중요한지 이해하지 못합니다. 정교하게 할 수 있습니까? 링커에서 중복 인라인 함수 정의를 제거 할 수 있으면 중복 반영 정보의 문제점은 무엇입니까? 어쨌든 디버거를 위해 심볼 정보가 객체 파일에 추가되지 않습니까?
Rob Kennedy

1
문제는 리플렉션 정보가 유효하지 않을 수 있다는 것입니다. 컴파일러가 클래스 정의의 80 %를 제거하면 리플렉션 메타 데이터는 무엇을 말합니까? C # 및 Java에서 언어는 클래스를 정의하면 정의 된 상태를 유지합니다. C ++을 사용하면 컴파일러에서이를 최적화 할 수 있습니다.
jalf December

1
@Rob, 최적화는 또 다른 요점이며 여러 클래스 합병증과 관련이 없습니다. 내가 의미하는 바에 대해서는 @jalf의 의견 (및 그의 대답)을 참조하십시오.
Johannes Schaub-litb

4
reflect <T>를 인스턴스화하면 T의 정보를 버리지 마십시오. 이것은 해결할 수없는 문제처럼 보이지 않습니다.
Joseph Garvin

3

C ++에서 리플렉션을 사용하는 경우가 많으며 템플릿 메타 프로그래밍과 같은 컴파일 타임 구문을 사용하여 적절하게 해결할 수 없습니다.

N3340 은 C ++에서 리플렉션을 도입하는 방법으로 풍부한 포인터를 제안합니다. 무엇보다도 기능을 사용하지 않으면 기능 비용을 지불하지 않는 문제를 해결합니다.


2

Alistair Cockburn에 따르면 반사 환경 에서는 서브 타이핑을 보장 할 수 없습니다 .

리플렉션은 잠재 타이핑 시스템과 더 관련이 있습니다. C ++에서, 당신은 당신이 가진 타입을 알고 당신이 그것으로 무엇을 할 수 있는지 알고 있습니다.


보다 일반적으로, 정의되지 않은 동작을 도입하지 않고 존재하지 않는 기능이 있는지 확인하는 기능을 통해 해당 기능을 이후 버전의 클래스에 추가하면 기존 프로그램의 잘 정의 된 동작이 변경 될 수 있습니다. 결과적으로 해당 기능을 추가해도 문제가 발생하지 않을 수 있습니다.
supercat

2

리플렉션은 전 처리기 지시문과 같은 선택 사항 일 수 있습니다. 같은 것

#pragma enable reflection

그렇게함으로써 우리는이 pragma 라이브러리가 성찰없이 (토론 된 오버 헤드없이) 생성 될 수 있기 때문에 두 세계를 모두 최대한 활용할 수 있으며, 속도 나 사용 편의성을 원하는지 여부에 따라 개별 개발자가 될 것입니다.


2

C ++가 가질 수있는 경우 :

  • 변수 이름, 변수 유형 및 const수정 자에 대한 클래스 멤버 데이터
  • 함수 인수 반복자 (이름 대신 위치 만)
  • 함수 이름, 반환 유형 및 const수정 자에 대한 클래스 멤버 데이터
  • 부모 클래스 목록 (정의 된 순서와 동일)
  • 템플릿 멤버 및 부모 클래스에 대한 데이터; 확장 된 템플릿 (실제 유형을 의미하는 것은 리플렉션 API에 사용할 수 있으며 '가는 방법에 대한 템플릿 정보'는 아닙니다)

오늘날의 웹 및 데이터베이스 응용 프로그램 (모든 orm, 메시징 메커니즘, xml / json 파서, 데이터 직렬화 등)에서 널리 사용되는 유형없는 데이터 처리의 핵심에서 매우 사용하기 쉬운 라이브러리를 만들기에 충분합니다.

예를 들어, Q_PROPERTY매크로 (Qt 프레임 워크의 일부)가 지원하는 기본 정보 ( http://qt.nokia.com/doc/4.5/properties.html 은 클래스 메소드 및 e)를 포함하도록 확장되었습니다.-C ++ 및 일반적으로 소프트웨어 커뮤니티.

필자가 언급 한 반영은 의미 론적 의미 나 더 복잡한 문제 (주석 소스 코드 라인 번호, 데이터 흐름 분석 등)를 다루지 않지만 언어 표준의 일부일 필요는 없다고 생각합니다.


@ 블라드 : 예, 언어에 대한 반영을 지원하는 기능을 추가하면 언어로 반영됩니다. 이것은 언어위원회가 결정한 경우에만 발생할 수 있으며 2011 년 기준이 아닌 것으로 생각되며 AD 2020 년 이전에 또 다른 C ++ 표준이 있는지 의심합니다. 좋은 생각입니다. 그 동안 진전을 이루려면 C ++을 벗어나야 할 것입니다.
Ira Baxter


0

C ++의 반영, C ++을 데이터베이스 액세스, 웹 세션 처리 / http 및 GUI 개발을위한 언어로 사용하려면 매우 중요하다고 생각합니다. 리플렉션이 없으면 ORM (Hibernate 또는 LINQ와 같은), 클래스, 데이터 직렬화 및 기타 여러 가지 요소 (처음에는 유형이없는 데이터를 사용하여 클래스의 인스턴스를 작성해야 함)를 포함하는 XML 및 JSON 파서가 방지됩니다.

빌드 프로세스 중에 소프트웨어 개발자가 사용할 수있는 컴파일 타임 스위치를 사용하면 이러한 '사용하는 비용에 대한 비용'문제를 제거 할 수 있습니다.

펌웨어 개발자는 직렬 포트에서 데이터를 읽기 위해 리플렉션이 필요하지 않습니다. 그런 다음 스위치를 사용하지 마십시오. 그러나 C ++을 계속 사용하려는 데이터베이스 개발자는 데이터 멤버와 데이터베이스 구성간에 데이터를 매핑하는 끔찍하고 유지하기 어려운 코드로 끊임없이 단계를 밟고 있습니다.

Boost 직렬화 나 다른 메커니즘은 실제로 리플렉션을 해결하지 못합니다. 컴파일러에서 수행해야합니다. 일단 완료되면 C ++은 다시 학교에서 힘들어지고 데이터 처리를 다루는 소프트웨어에 사용됩니다.

나 에게이 문제 # 1 (및 네이티브 스레딩 프리미티브는 문제 # 2).


4
누가 C ++ DB Access, 웹 세션 hnadling 또는 gui dev의 언어로 사용될 것이라고 말했습니까? 이런 종류의 물건에 사용할 훨씬 더 나은 언어가 많이 있습니다. 그리고 컴파일 타임 스위치는 문제를 해결하지 못합니다. 일반적으로 리플렉션 활성화 또는 비활성화 결정은 파일 단위가 아닙니다. 개별 유형에서 사용하도록 설정하면 작동 할 수 있습니다. 프로그래머가 유형을 정의 할 때 속성 또는 이와 유사한 속성으로 지정할 수 있으면 해당 유형의 리플렉션 메타 데이터가 생성되어야하는지 여부입니다. 그러나 글로벌 스위치? 10 %를 더 단순하게 만들기 위해 lnaguage의 90 %를 움켜 쥐고 있습니다.
jalf

그런 다음 크로스 플랫폼이며 GUI에 액세스 할 수있는 프로그램을 원한다면 어떻게해야합니까? 융통성이없는 자바 스윙? 창문 만 C #? 그러나 진실은 말해야하며, 진실은 실행 가능한 코드로 컴파일되고 GUI 인터페이스와 데이터베이스에 대한 액세스를 제공하는 많은 프로그램이 있다는 것입니다. 따라서 일부 데이터베이스와 GUI 지원을 사용해야합니다 ... QT 사용. (MT라는 이름으로
불리어야

1
@ Coyote21 : C #은 몇 년 동안 Windows 전용이 아니 었습니다. (모노의 팬은 아니지만 대부분의 경우 잘 작동합니다.) Swing은 Java 용 GUI 툴킷이 아닙니다. 크로스 플랫폼을 원한다면 어느 쪽이든 더 나은 선택이 될 것입니다. C ++은 사소한 일을하는 경우 항상 플랫폼 특정 부분을 여기 또는 거기에서 가질 것입니다.
cHao

ORM에 대한 성찰이 필요한 이유는 없습니다. 템플릿을 사용하면이 모든 것을 달성 할 수 있습니다. C ++에 ORM을 제공하는 많은 프레임 워크가 있습니다.
MrFox

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