효과적인 C ++ 절 44 : 템플릿 및 (매개 변수 코드를 뽑아 템플릿과 관련이없는)의 제네릭 프로그래밍

반복 전략에 대응하는 코드

함수의

  • 코드가 같은 경우 우리는 (하나 이상) 특정 기능을 쓰기 가정, 우리가 생각하는, 그래서 이러한 기능 중 일부가 프로그램이 반복이 코드입니다
  • 이 시간에 나는 할 수 있도록 이러한 기능의 공통 부분을 추출하고, 다른 함수에 배치 될 새로운 기능은이 기능들을 가지고 호출 그래서. 이것은 코드를 감소시키는 효과를 달성

클래스의 목적

  • 우리는 클래스 세트를 작성하고 우리가 생각하는, 그래서 일부 지역에서 이러한 클래스는, 동일 가정 프로그램이 반복이 코드입니다
  • 우리가 할 수있는이 시간에 그래서 함께 추출 이러한 클래스의 일부가 될 새로운 클래스를 생성 한 다음 이러한 클래스는 새로운 클래스로부터 물려받은 수 있습니다. 이것은 코드를 감소시키는 효과를 달성

템플릿 (템플릿 함수 / 클래스 템플릿)입니다

  • 우리는 템플릿을 사용할 때 코드 만 인스턴스화 할 것이라는 점을 알고있다, 각 인스턴스에 대한 코드에 해당하는 코드를 생성 그래서 모든 사람을 위해, 인스턴스화 사이에 코드 중복을 생성 할 수 현상
  • 일반 함수 / 클래스 코드 반복을 쉽게 (코드하여) 보여진다. 그러나 템플릿, 그것은 쉽게에만 템플릿이 인스턴스화되기 때문에, 당신은 생성 된 컨텐츠를 템플릿을 알고, 그것을 발견하지 않는 것입니다

둘째, 시범 케이스

  • 우리는 고정 된 크기의 정방 행렬을 표현하기 위해 사용되는 그러한 템플릿 클래스가 있다고 가정하자 ,이 행렬은 역행렬 동작 지원 방법. 다음과 같이 코드입니다 :
//矩阵的元素类型为T,矩阵的大小为n*n类型(模板第二个类型为非类型参数)
template<typename T, std::size_t n>
class SquareMatrix {
public:
    void invert(); //求逆矩阵
};
  • 우리가, 다음 호출이 가정 반전 () 함수를 호출하기 위해서는 코드를 부풀게 될 수 있습니다. 다음과 같은 이유 :
    • 5 * 10 * 5 행렬 (10) (전환이라고 매트릭스) 아래에서 함수 매트릭스의 반전을 위해 사용
    • 그러나, 다른 코드의 매트릭스 형상 크기 반전 또한 ()의 처리 매트릭스에 동일 인버트 () 구현 코드보기, 이에 따른 두 개의 템플릿이 생성되는 상기 코드 중복 여기서 생성
SquareMatrix<double,5> sm1;
sm1.invert();

SquareMatrix<double,10> sm2;
sm2.invert();

우선 개정

  • 우리는 이제 다음 상속 계층 구조를 확립 있도록 때문에 코드 반전 (), 중복 생성합니다 . 다음과 같이 코드입니다 :
    • 우리는 처리 할 수있는 행렬의 크기를 표시하는 데 사용, 단지 매트릭스 방식을 수용 (반전에 매개 변수를 추가, SquareMatrixBase라는 SquareMatrix 클래스 템플릿을) 수정
    • SquareMatrix 템플릿 행렬의 템플릿 매개 변수를 size_t 크기를 제공하고, 그 클래스를 상속 추가하는 과정을 나타내는 데 사용
//不论SquareMatrix产生多少粉,SquareMatrixBase在代码中只产生一份
template<typename T>
class SquareMatrixBase {
protected:
    void invert(std::size_t matrixSize);
};

template<typename T,std::size_t n>
class SquareMatrix :private SquareMatrixBase<T>
{
private:
    using SquareMatrixBase<T>::invert; //避免派生类隐藏基类的invert函数
public:
    void invert() {
        this->invert(n); //为什么使用this,参阅条款43
    }
};
  • 첫 번째 이유 코드에 비해 비용 절감 여기 :
    • SquareMatrix 인스턴스화 할 때, 때문에 기능 반전 직접 호출 기본 클래스의 너무 많은 코드를 생성하지 않는
    • 기본 클래스 때문에하고 있기 때문에 서로 다른 크기와 템플릿 클래스의 예는 상이한 행렬 반전되지 는 인버트 () 함수를 호출 할 수있는, 상기 행렬의 크기에 따라 클래스 코드 템플릿을 생성하기 때문에
  • 일부 구문 노트 :
    • SquareMatrixBase 기능 파생 클래스를 달성하기 때문에, () 함수의 반전 SquareMatrixBase가되도록 보호 된 바와 같이, 직접 외부 조작 금지 선언 SquareMatrixBase
    • SquareMatrix는 "앞에 도입으로 인해 기술의 사용으로, SquareMatrixBase에 개인 상속을 사용 더 - 이용 약관 -의 (뭔가 아웃을 달성하기 위해 따라) 구현 (당신은 절 38, 39 볼 수 있습니다) 기술을"
    • 또한, 기본 클래스 인버트 () 호출에 SquareMatrix 인버트 ()에서 이 포인터를 사용하여 (한 조항의 내용을 볼 수있는 43)

두 번째 개정

  • 이제 문제가 있습니다 :
    • SquareMatrixBase () 데이터 매트릭스의 처리를 완료,하지만 어떻게 당신은 어디에서 SquareMatrixBase 과정을 알 수 있습니까?
    • 따라서 SquareMatrix는 () 방법을 사용해야 SquareMatrixBase로 데이터 전송 동작 ()
  • 해결 방법 :
    • ① (바람직 법) : SquareMatrixBase () : 반전 () 처리 될 데이터를 표현하는데 사용되는 포인터 파라미터 행렬 제공한다. SquareMatrixBase ()가 작동 많은 회원에게 방법 SquareMatrixBase (있는 경우 데이터의 전체 클래스가 필요합니다), 다음 방법의 각 구성원에 대한 포인터를 제공해야하므로 따라서 그래서, 바람직하지 않은 동일한 전력 공급 부분을 바람직하지 않은 방법
    • ② (이 수정 동작에있어서) SquareMatrixBase에 ()를 조작 할 수있는 매트릭스 (파생 된 클래스로부터이 메모리)에 저장하기 위해 데이터 메모리에 대한 포인터를 저장한다. 다음과 같이 코드입니다 :
template<typename T>
class SquareMatrixBase {
    //其余同上
protected:
    SquareMatrixBase(std::size_t n, T* pMem)
        :size(n), pData(pMem) {}

    void setDataPtr(T* ptr) { pData = ptr; } //更改pData的数据
private:
    std::size_t size; //矩阵的大小
    T* pData;         //指向矩阵的内容
};
  • 다음 파생 된 클래스 코드는 다음과 같이 그 클래스 처리 코드의 실제 메모리 매트릭스 자체 데이타베이스에 대한 포인터를 전달하는 바와 같이 다음이다 :
template<typename T, std::size_t n>
class SquareMatrix :private SquareMatrixBase<T>
{
    //其他同上
public:
    SquareMatrix():
        SquareMatrixBase<T>(n, data) {} //将存储矩阵数据的指针传递给基类
private:
    T data[n*n]; //存储矩阵的实际数据
};

셋째 개정

  • 이어 "두 번째 개정,"우리는 매트릭스 데이터 SquareMatrix 클래스에 저장됩니다 위의 개체 자체의 원인은 매우 큰 SquareMatrix입니다
  • 또 다른 방법은 다음과 같습니다 힙 매트릭스에 저장된 데이터 . 다음과 같이 코드입니다 :
template<typename T, std::size_t n>
class SquareMatrix :private SquareMatrixBase<T>
{
public:
    SquareMatrix():
        SquareMatrixBase<T>(n, 0), pData(new T[n*n])
    {
        //将它的一个副本交给base class
        this->setDataPtr(pData.get());
    }
private:
    boost::scoped_array<T> pData;
};
  • 세 수정 후, 코드는 특정 세부 사항이 비교에 대해 최적화되었다 :
    • SquareMatrix 멤버 함수는 단순히 SquareMatrixBase 된 invoke 버전을 인라인 것
    • 객체 클래스 공유 SquareMatrix "동일한 요소 유형이지만 다른 매트릭스 크기 보류"를 SquareMatrixBase의 클래스
    • 그리고 우리는 다른 SquareMatrix 객체를 다른 객체에 대한 객체에 대해 (예컨대 SquareMatrix <이중 5> 및 <이중 10> SquareMatrix), 조작 의지하지 걱정 동작 그렇게하면 setDataPtr () 함수 SquareMatrixBase을 첨가 데이터 우리 setDataPtr ()은 행렬 데이터 포인터에 설치되어 사용하기 때문에 SquareMatrixBase
  • 코드 효율성에 대한 몇 가지 지침 :
    • ①SquareMatrix는 인버트 () 함수, 더 나은 코드를 생성 () 함수의 공유 버전 (SquareMatrixBase의 a)에 비해 반전된다. SquareMatrix 예에서는, 행렬의 크기는이 명령이 직접 피연산자로서 생성된다로 접는 포함 일정 최적화함으로써 다양한 전달하는 것이 가능하고, 컴파일러 상수이다. 이 SquareMatrixBase에서 수행 할 수 없습니다
    • ② 반전 () (SquareMatrixBase에서)의 단 하나의 버전과 다른 크기의 행렬, 따라서 또한 작업 세트의 프로그램의 크기를 줄이고, 실행 파일의 크기를 줄일 수 있으며, 지침을 강화하기 위해 캐시 영역 참조 집중화를 알려줍니다. 이 프로그램은 더 빠른 실행을 할 수 있습니다
      • 소위 작업 세트에서 실행을위한 과정을 의미한다 "가상 메모리 환경,"그룹은 메모리 페이지를 사용하는 것이
    • 또 다른 테마 ③ 성과 평가는 개체의 크기와 관련되어 우리가 데이터 매트릭스에 대한 포인터에 SquareMatrix에 저장 SquareMatrix 잠금 장치의 크기가 증가 만든 개체 수 있도록.
      • 또 다른 방법 : 포인터 SquareMatrix 제거되도록 상기 데이터 매트릭스 보호 기억 SquareMatrixBase 포인터. 그러나 이것은 캡슐화의 손실을 초래할 수있는, 또 다른 자원 관리 및 복잡성에 혼란을 초래할 수있다 (22 절 참조)
      • 따라서, 우리는 일부 공간의 증가에도 불구하고, 포인터를 저장 SquareMatrix하지만, 장점과 단점, 그것은 가치가있다

셋째, 추가

  • 이 조항은 붓기가 발생할 수도 비 형 템플릿 매개 변수 (비 형 템플릿 매개 변수), 사실, 유형 매개 변수 (유형 매개 변수)에 의해 초래 확장을 논의하는 것입니다

예를 들면

  • 대부분의 플랫폼은 int로 긴 같은 바이너리 표현이
  • 따라서 벡터 <INT>와 벡터 <긴> 멤버 함수는 동일한 가질 수있다 - 원인 코드 중복 / 확장
  • 일부 링커 (링커) 동일한 기능의 코드를 달성하기 위해 합병되지만, 일부는하지 않습니다
  • 일부 템플릿은 따라서 두 가지 버전, 그 결과 코드 중복 / 확장을 int로서 구현과 긴

예를 들면

  • 대부분의 플랫폼에서 모든 포인터 타입은 동일한 바이너리 표현이
  • 포인터는 예를 들어 템플릿, 일람 <INT의 *>리스트를 보유 그렇다면 <CONST INT *>에서 <SquareMatrix <긴 3> *> 등이, 각각 대응하고 각 멤버 함수 경향이 사용하는 고유 기본 구현
  • 특정 부재의 기능과 동작 강한 포인터 타입 (즉, T의 *)를 얻을 경우, 일반적으로, 형태없이 작동되도록 서로 불러야 수단과 접함으로써 행해진 다 (즉, 무효 *) 함수 포인터 실제 작업
  • 일부 C ++ 표준 라이브러리 구현 버전은 실제로 벡터, 양단 큐, 목록 및 기타 템플릿이 일을한다. 당신이 코드를 부풀게를 발생할 수있는 템플릿을 걱정하는 경우, 당신은 또한 당신의 템플릿은 이러한 기술을 사용 할 것

IV 요약

  • 어떤 템플릿은 증산 파라미터 의존성 코드 템플릿을 발생하지 않도록, 복수의 클래스들 및 함수들을 생성 템플릿
  • 때문에 종종 제거 할 수 팽창에 의한 비 형 템플릿 매개 변수에 대한 코드, 연습은 템플릿 매개 변수 기능 매개 변수 나 클래스 멤버 변수를 대체하는 것입니다
  • 매개 변수 유형 코드 확장에, 그 접근 방식이 동일한 유형의 이진 표현을 수 있도록하는 것입니다으로 감소되는 경향이 이제 공유 코드를 달성하는 데 인해 발생
출시 1525 원저 · 원의 찬양 (1084) ·은 45 + 조회수

추천

출처blog.csdn.net/qq_41453285/article/details/104856465