2009-07-22 4 views
33

일반화 대 다형성에 관한 결정을 내려야합니다.C++ 표준 실습 : 가상 인터페이스 클래스와 템플릿

시나리오가 표준입니다. 내 모 놀리 식 상호 의존 코드를 더 모듈화되고, 깨끗하고 확장 가능하게 만들고 싶습니다. 디자인 원칙의 변경이 가능한 단계인데, 그리고 내가보기에 매우 바람직하다.

순전히 가상 기본 클래스 (인터페이스) 또는 템플릿을 소개합니까?

나는 템플릿 옵션에 대한 기본 사항을 알고 : 적은 간접, 더 나은 성능, 더 등등 하지만 후기 바인딩 및 컴파일.

stl은 상속을 많이 사용하지 않으며 부스트도하지 않습니다. 하지만이 코드는 프로그래머가 코드를 2 줄씩 사용하는 아주 작은 기본 도구를 목표로하고 있다고 생각합니다.

플러그인의 큰 코드 조각과 기능을 교환 할 수 있어야하고, 업데이트 가능함 등의 경우 런타임 또는 런타임 중에 더 적합하다고 생각합니다.

글쎄, 내 시나리오는 어느 정도 거짓말입니다.

런타임시 코드 조각을 교환 할 필요가 없습니다. 컴파일 시간이 좋습니다. 일반적으로 매우 중앙에서 자주 사용되는 기능 인 은 큰 블록으로 논리적으로 분리 할 수 ​​없습니다.

이렇게하면 템플릿 솔루션이 다소 필요합니다. 나에게도 그것은 다소 깨끗해 보인다.

큰 영향이 있습니까? 아직 인터페이스가 있습니까? ? 그들은 언제입니까? 표준 C++ 스타일을 더 잘 준수합니까?

나는 이것이 주관적인 경계에 있다는 것을 알고 있지만, 나는 실제로 어떤 경험이 에 관심이있다. 나는 Scott Meyers의 복사본을 가지고 있지 않다. C++ 나는 너희들에게 희망을 걸었다. :)

답변

20

유형이 있어야 할 때 동적 인 다형성 (상속, 가상)이 일반적으로 올바른 선택이다. (예를 들어, 플러그인 아키텍처에서) 런타임에 변경할 수 있습니다. 유형을 컴파일시에만 변경해야하는 경우 정적 다형성 (템플릿)을 사용하는 것이 더 좋습니다.

템플릿의 잠재적 단점은 1) 일반적으로 머리글에 정의해야하기 때문에 (더 많은 코드가 #include된다는 의미입니다.) 이로 인해 컴파일 시간이 느려질 수 있습니다.

하지만 디자인 상으로는 가능한 경우 템플릿을 사용할 때 어떤 문제도 볼 수 없습니다.

표준 C++ 스타일에 더 부합합니까?

"표준 C++ 스타일"이 무엇인지에 따라 다릅니다. C++ 표준 라이브러리는 모든 것을 약간 사용합니다.STL은 모든 것을 위해 템플릿을 사용하고 약간 오래된 IOStreams 라이브러리는 상속과 가상 함수를 사용하며 C에서 상속받은 라이브러리 함수는 물론 둘 다 사용하지 않습니다.

요즘 템플릿은 가장 인기있는 선택이지만, 나는 이것이 가장 "표준적인"접근 방식이라고 말하고 싶습니다.

+3

글쎄, 인터페이스보다는 템플릿을 사용하는 한 가지 문제가 있습니다. 요구 사항이 완전히 암묵적입니다. 순수 가상 함수를 구현해야 할 때 정확한 서명이 주어집니다. 그러나 _AllocT 나 Iter와 같은 템플릿 유형을 볼 때 클래스가 필요하거나 클래스가되어야하는지 여부는 알 수 없습니다. 귀하의 유일한 방법은 그것에 대해 괜찮은 설명서를 찾는 것입니다, 나는 오늘 자신의 stl 호환 할당 자 클래스를 만들려고 할 때 문제가있었습니다. – Virus721

+3

"알기 만하면 괜찮은 설명서를 찾는 것입니다"- 또는 컴파일러가 컴파일러가 찾을 수없는 것에 대해 불평하는 기능을 보려고 시도하는 중입니다. 또한 개념은이 문제를 해결하기위한 것입니다. (인터페이스 였더라도 여전히 괜찮은 문서를 찾아야합니다.재정의 할 함수를 아는 것만으로는 충분하지 않습니다. 당신은 또한 그들의 의미가 무엇인지 알아야하고, 인터페이스는 당신에게 그것을 말하지 않는다). 아직도, 당신 말이 맞아요. 언어가 둘 다 지원하는 이유가 있습니다. :) – jalf

8

이것은 잘못된 반대입니다. 예, 상속 및 가상 함수의 주요 용도는 iostreams입니다.이 라이브러리는 매우 오래되었으며 std 라이브러리의 나머지 부분과 완전히 다른 스타일로 작성되었습니다.

그러나 부스트와 같은 "멋진"최신 C++ 라이브러리 중 상당수는 런타임 다형성을 사용하므로 템플릿을 사용하여 더욱 편리하게 사용할 수 있습니다.

boost::anystd::tr1::function (이전에는 부스트로부터)이 좋은 예이다.

컴파일 타임에 구체 유형이 알려지지 않은 단일 항목 컨테이너입니다 (값을 얻기위한 자체 캐스트 연산자가 있으므로 any에서 특히 명확합니다). 고전적인 객체 지향 다형성의

+0

+1 귀하의 답변은 매우 계몽 적이지만, 질문에 따라 나는 jalf의 조언을 받아 들였습니다. 감사. – AndreasT

9

속성 :

  • 객체가 런타임에 바인딩; 이것은 더 유연하지만 런타임에 더 많은 리소스 (CPU)를 소비합니다.
  • 강력한 타이핑은 다소 더 많은 유형 안전성을 제공하지만 dynamic_cast의 필요성 (그리고 잠재력이 고객의 얼굴에 날아갈 수 있음)은

    • 컴파일시 바인딩이 더 공격적으로 optimizat 수 있습니다 :
    • 아마 더 널리 알려지고 이해하지만,
    • 은 "고전적인"깊은 상속 계층 구조 템플릿 나에게 컴파일 타임 다형성의

    속성을 끔찍한 것 하지만 실행 시간 유연성을 보장하지 않습니다.

  • 오리 유형 지정은 더 어색한 것처럼 보일 수 있지만 보통 컴파일 타임 오류입니다.
  • 은 때때로 읽고 이해하기가 어려울 수 있습니다. 개념이 없으면 컴파일러 진단이 때로는 엉망이 될 수도 있습니다.

둘 중 하나를 결정할 필요가 없습니다. 당신은 자유롭게 혼합 할 수 있고 그들 둘다 (그리고 다른 많은 숙어와 패러다임)을 섞을 수 있습니다. 종종 이는 매우 인상적인 (그리고 표현적인) 코드로 이어집니다. (예를 들어, 소거 (erasure)와 같은 것들을보십시오.) 패러다임을 영리하게 혼합함으로써 가능한 것을 알기 위해서는 Alexandrescu의 "Modern C++ Design"을 검색하고 싶을 것입니다.

+0

OOP에서 강력한 타이핑? 그것은 심지어 말이되지 않습니다. 컴파일 타임의 다형성 (polymorphism)으로부터 타입 안전성의 이점을 얻을 수 있습니다. OOP에서는 지우개를 입력하고 (예를 들어 인터페이스 뒤에 실제 유형을 숨김으로써) up/downcasts는 type safty에 대한 희망을 거의 없애줍니다. – jalf

+2

당신은 확실히 옳습니다. 그러나 내가 의미하는 바는 실행 시간 다형성에서, 당신이 얻는 것은 인터페이스의 고의적 인 구현이며, 컴파일 타임의 다형성 (duck typing)은 임의의 우연한 일치를 받아 들일 수 있다는 것을 확신 할 수있다. 어떻게 이렇게 좋습니까? – sbi

0

필자의 관점에서 볼 때, 그것은 당신이 가장 잘한 것입니다. OO에 대한 더 많은 경험이 있다면 OO를 사용하십시오. 제네릭에 대한 경험이 더 많은 경우 제네릭을 사용하십시오.

두 기술 모두 사용할 수있는 많은 기능을 의미하는 일부 동등한 패턴이 있습니다. OO의 EG 전략과 일반 정책의 정책 대 OO의 템플릿 방법 대 일반적으로 반복되는 템플릿 패턴 비교.

리펙터 제작 코드를 이미 계획했으나 구조가 약간 이상하다고 생각하는 경우.1 년이나 2 년 후에 기술을 더 잘 이해하면 코드를 리팩토링 한 방법을 후회할 수 있기 때문에 새로운 디자인 기법을 사용하는 것은 핑계 거리로 사용하지 마십시오. 기술을 배우면서 적용 할 때 새로운 유연성을 도입하는 것은 매우 쉽습니다. 기술에 익숙하지 않은 경우 기존 코드의 디자인을 개선하는 것이 목적입니다. 코드에서 큰 남근 기호를 만드는 대신 디자인을 개선하는 방법을 어떻게 알 수 있습니까?

개인적으로 나는 OO에서 더 나아졌으며 이해하기 쉽고 대부분의 사람들이 바꿀 수있는 깨끗한 디자인을 제작할 수 있다는 것을 알기 때문에 그것을 좋아하는 경향이 있습니다. 가장 일반적인 제 코드는 다른 제네릭 코드 (예 : 반복자 작성 또는 알고리즘 일반 함수)와의 인터페이싱을 목표로합니다. 내 접시에 좀 더 많은 경험을 삽 한 후

4

, 내가 좋아하지 않는 템플릿에서 몇 가지가있다 : 쓸모있는 언어 인에서 템플릿 메타 프로그래밍의 자격을 박탈 특정 단점이 있습니다

  • 은 가독성 : 너무 많은 브라켓, 너무 많은 비 언어 시행 (때문에 오용) 규칙 프로그래밍 언어에서 일반적인 발전을받은 사람에 대한
  • , 템플릿은 읽을 수 싶게 이해할 수
  • 때때로 시도 사람 같은 느낌 (단지 부스트 BGL보고) ~에 awk에서 C++ 코드 생성기를 사용하십시오.
  • 컴파일러 오류 메시지는 기능과 같은 몇 가지 기본적인 "언어"를 얻기 위해 너무 많은 해킹이 필요합니다 (대다수는 C++ 0x로 수정 됨)
  • 구현 파일에 템플릿이 없으므로 머리말 전용 라이브러리가 생성됩니다 (양면 검입니다).
  • 일반적인 IDE의 코드 완성 기능은 템플릿에별로 도움이되지 않습니다.
  • MPL에서 큰 일을하는 것은 "애매한 것"으로 보이며 다른 단어를 찾을 수 없습니다. 템플리트 된 코드의 모든 라인은 해당 템플리트 유형에 대한 제한 조건을 생성하며, 텍스트 대체 유형으로 강제 적용됩니다. 상속 계층에는 본질적으로 의미가 있습니다. 템플릿 구조에는 아무 것도 없습니다. 그것은 모든 것이 무효 인 것과 같고 컴파일러는 segfault가 있는지를 알려줍니다.

내가 말한 모든 것은 기본 유틸리티와 라이브러리에서 아주 성공적으로 사용된다. 고급 기능이나 하드웨어와 관련된 내용을 작성하는 것은 나를 대신하지 않는 것 같습니다. 의미 나는 건물 블록을 템플릿 처리하지만 고전적인 방법으로 집을 짓는다.

0

큰 코드베이스에서 둘 다 사용합니다. 유형이 컴파일 타임에 알려지면, 템플릿으로 디자인합니다. 런타임에만 알려져있을 때는 가상 함수를 사용합니다. 나는 가상 함수가 프로그램하기 쉽고 나중에 읽는 것이 쉽다는 것을 알았지 만, 성능이 중요하고 템플릿 다형성 (실제로 다형성이라고 부를 수 있다면)이 인라인 될 수 있다는 사실이 실제로 도움이됩니다.

관련 문제