C++사용자 정의 형식의 교체 기 작업 실현

동기
우 리 는 STL 이 많은 알고리즘(\#include)을 실현 했다 는 것 을 알 고 있 습 니 다.프로젝트 가 STL 기반 으로 구축 되 었 다 면 기 존 코드 를 최대 화 할 수 있 는 것 이 가장 좋 습 니 다.STL 에서 용기 와 알고리즘 사이 의 다 리 는 교체 기다.따라서 사용자 정의 형식의 용 기 를 정의 한 다음 교체 기의 실현 이다.
STL 의 교체 기
교체 기 모델 은 전형 적 인 디자인 모델 이 고 STL 의 교체 기 는 템 플 릿 의 일부 특성 과 기능 을 사용 하 는 것 을 실현 하 였 으 며 여기 서 조금 소개 하 겠 습 니 다.
다음은 STL 에서 구조 체 iterator 의 정의 입 니 다.이 정 의 는 뒤의 알고리즘 다 형 과 추출 시(구체 적 으로 책 에서 소개)에 사 용 됩 니 다.
그 중의Category 와Ty 는 기본 값 이 없어 서 스스로 인 자 를 줘 야 합 니 다.
_Ty 는 원소 의 유형 입 니 다.

template<class _Category,
 class _Ty,
 class _Diff = ptrdiff_t,
 class _Pointer = _Ty *,
 class _Reference = _Ty&>
 struct iterator
 { // base type for iterator classes
 typedef _Category iterator_category;
 typedef _Ty value_type;
 typedef _Diff difference_type;
 typedef _Diff distance_type; // retained
 typedef _Pointer pointer;
 typedef _Reference reference;
 };
그리고Category 는 교체 기의 유형 으로 주로 다음 과 같은 몇 가지 가 있다.

// ITERATOR STUFF (from <iterator>)
// ITERATOR TAGS (from <iterator>)
struct input_iterator_tag //  
 { // identifying tag for input iterators
 };
struct _Mutable_iterator_tag //  
 { // identifying tag for mutable iterators
 };
struct output_iterator_tag //  
 : _Mutable_iterator_tag
 { // identifying tag for output iterators
 };
struct forward_iterator_tag //    
 : input_iterator_tag, _Mutable_iterator_tag
 { // identifying tag for forward iterators
 };
struct bidirectional_iterator_tag //     
 : forward_iterator_tag
 { // identifying tag for bidirectional iterators
 };
struct random_access_iterator_tag //    
 : bidirectional_iterator_tag
 { // identifying tag for random-access iterators
 };
//...
사용자 정의 교체 기
나 는 교체 기 에 다음 과 같은 조작 이 있 기 를 바란다.*,+.또한 교체 기 를 통 해 count 를 호출 하려 고 합 니 다.if 함수.그럼 countif 어떤 조작 부 호 를 사용 하 시 겠 습 니까?

// TEMPLATE FUNCTION count_if
template<class _InIt,
 class _Pr> inline
 typename iterator_traits<_InIt>::difference_type
 _Count_if(_InIt _First, _InIt _Last, _Pr _Pred)
 { // count elements satisfying _Pred
 typename iterator_traits<_InIt>::difference_type _Count = 0;
 for (; _First != _Last; ++_First)
 if (_Pred(*_First))
  ++_Count;
 return (_Count);
 }
++를 사용 하 는 것 을 볼 수 있 습 니 다.그래서 우리 의 교체 기 는 이것 을 모두 실현 해 야 한다.코드 는 간단 합 니 다:

#include<iterator>
template<class T>
class MyIterator : public iterator<input_iterator_tag, T>{
 public:
 MyIterator(T* p){
  _ptr = p;
 }
 //  
 MyIterator& operator = (const MyIterator &iter)
 {
 _ptr = iter._ptr;
 }
 //   
 bool operator != (const MyIterator &iter)
 {
 return _ptr!= iter._ptr;
 }
 //  
 bool operator == (const MyIterator &iter)
 {
 return _ptr == iter._ptr;
 }
 //    
 MyIterator& operator ++ ()
 {
 _ptr++;
 return *this;
 }
 //    
 MyIterator operator ++ (int)
 {
 MyIterator tmp= *this;
 _ptr++;
 return tmp;
 }
 //  
 T& operator * ()
 {
 return *_ptr;
 }
 private:
 T* _ptr;//       ,          
};
사용자 정의 용기
다음은 간단 한 수조 용 기 를 제시 하여 수조 의 기본 조작 을 실현 하 였 다.방금 정 의 된 교체 기 를 내장 하 였 습 니 다.

template<class T>
class myVector{
public:
 typedef MyIterator<T> iterator;//             ,          
 myVector(){
 _selfElems = new T[32];
 _count = 32;
 init();
 }
 myVector(int n){
 _selfElems = new T[n];
 _count = n;
 init();
 }
 void init(){
 memset(_selfElems, 0, sizeof(T)* _count);
 }
 //    
 T& operator[](int i){
 return _selfElems[i];
 }
 iterator begin(){
 return iterator(_selfElems);
 }
 iterator end(){
 return iterator(_selfElems + _count);
 }
 int size() const {
 return _count;
 }
private:
 T* _selfElems;
 int _count;
};
\#\#테스트
vector 와 자체 용기 my Vector 를 정의 하고 교체 기 를 통 해 접근 하 며 교체 기 를 통 해 conunt 를 사용 합 니 다.if 함수

bool eq_10(int k){
 return k == 10;
}
int main(){
 //     
 myVector<int> mv(10);
 mv[3] = 10; mv[9] = 10;
 myVector<int>::iterator it = mv.begin();
 cout <<"mv:"<<endl;
 while (it != mv.end()){
 cout << *(it++) << " ";
 }
 cout << endl;
 cout << count_if(mv.begin(), mv.end(), eq_10) << endl;
 //STL   
 vector<int> v(10,0);
 v[3] = 10; v[9] = 10;
 vector<int>::iterator it1 = v.begin();
 cout << "v:" << endl;
 while (it1 != v.end()){
 cout << *(it1++) << " ";
 }
 cout << endl;
 cout << count_if(mv.begin(), mv.end(), eq_10) << endl;
 getchar();
 return 0;
총화 와 사고
그래서 쉽게 말 하면 자신의 용기 의 교체 기 를 정의 하고 교체 기 를 통 해 STL 의 알고리즘 함 수 를 호출 하려 면.먼저 iteroter 를 계승 한 다음 에 필요 한 조작 부 호 를 실현 하면 됩 니 다.그러나 구체 적 인 알고리즘 함 수 는 교체 기 유형 에 대해 요구 가 있 기 때문에 이것 은 스스로 파악 해 야 한다.
이 간단 한 예제 에 서 는 my Vector 의 지침(mv.ptr)도 count 를 호출 할 수 있 습 니 다.if 의 경우 STL 이 템 플 릿 편 특 화 기술 을 통 해 교체 기 도 네 이 티 브 지침 을 지원 하기 때 문 입 니 다.그러나 방문 요 소 를 모두 교체 기 에 넣 었 으 니 모든 용기 에 대해 통 일 된 방식 으로 접근 할 수 있 습 니 다.모든 용기 의 디 테 일 을 드 러 내지 않 아 도 됩 니 다(my Vector:ptr):

//T      
template<class T>
void display(T it, T end){
 T it1 = it;
 while (it1 != end){
 cout << *(it1++) << " ";
 }
 cout << endl;
 cout << count_if(it,end, eq_10) << endl;
}
int main(){
 //     
 myVector<int> mv(10);
 mv[3] = 10; mv[9] = 10;
 //STL   
 vector<int> v(10, 0);
 v[3] = 10; v[9] = 10;
 //vector   myVector         ,               
 display(mv.begin(), mv.end());
 display(v.begin(), v.end());
 getchar();
 return 0;
}
교체 기 는 용기 에 더 많은 기능 과 통용 성 을 부여 했다.
추가 지식:C++사용자 정의 교체 기(구현+두 칸 증가)
//효 과 는 매번 교체 기 에 두 칸 씩 이동 합 니 다.

#pragma once
//MyIterator.h
#include <iterator>
#include <exception>
template<typename Container>
class MyIterator :public std::iterator<std::random_access_iterator_tag, typename Container::value_type>
{
protected:
  Container& container;
  typename Container::iterator pos;
public:
  explicit MyIterator(Container& c) :container(c), pos(c.begin()){}
  MyIterator(const MyIterator& rhs) :container(rhs.container),pos(rhs.pos) {}
  MyIterator& operator =(const MyIterator& rhs)
  {
    throw_ex(rhs.container);
    pos = rhs.pos;
    return *this;
  }
  //--     ...
  MyIterator& operator ++()
  {
    auto tmp = container.end() - 1;
    if (pos == tmp)
      ++pos;
    else
      pos += 2;
    return *this;
  }
  bool operator ==(const MyIterator& rhs)const
  {
    try
    {
      if (&rhs.container == &container)
        return pos == rhs.pos;
      else
      {
        throw exception("    ");
      }
    }
      catch (exception &e)
      {
        cout << e.what();
        exit(EXIT_FAILURE);
      }
    }
bool operator !=(const MyIterator& rhs)const
{
  return !(*this == rhs);
}
typename Container::value_type & operator *()
{
      return *pos;
}
void begin()
{
  pos = container.begin();
}
void end()
{
  pos = container.end();
}
private:
  void throw_ex(const Container& c)
  {
    try
    {
      if (&c == &container)
        return;
      else
        throw exception("Copy     ");
    }
    catch (exception &e)
    {
      cout << e.what();
      exit(EXIT_FAILURE);
    }
  }
};
//       vector<T> vec     vec.begin()     begin(vec)
//            start(vec) over(vec)
template<typename Container>
MyIterator<Container> start(Container& c)
{
    MyIterator<Container> mi(c);
    mi.begin();
    return mi;
}
template<typename Container>
MyIterator<Container> over(Container & c)
{
    MyIterator<Container> mi(c);
    mi.end();
    return mi;
}
//main.cpp

#include <iostream>
#include <vector>
#include "MyIterator.h"
#include <list>
using namespace std;
//    iterator<std::random_access_iterator_tag,Container::value_type>      
template<typename Iterator>
void printIterator(const Iterator &It)
{
  cout << typeid(typename iterator_traits<Iterator>::iterator_category).name() << endl;
}
int main()
{
  vector<int> coll{ 1,2,3,4,5,6,7,8,9,10 };
  MyIterator<decltype(coll)> myit(coll);
  printIterator(myit);
  for (; myit != over(coll); ++myit)
  {
    cout << *myit << ends;
  }
  system("pause");
  return 0;
}
효과:

이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.잘못 이 있 거나 완전히 고려 되 지 않 은 곳 이 있 으 면 댓 글 토론 을 환영 합 니 다.아 낌 없 는 가르침 을 바 랍 니 다.

좋은 웹페이지 즐겨찾기