首页 > 代码库 > 模板类之间的友元关系实现Blob和BlobPtr
模板类之间的友元关系实现Blob和BlobPtr
16.12编写你自己版本的Blob和BlobPtr模板,包含书中未定义的多个const成员。
Blob.h(注意,成员函数的声明和定义要放在一个头文件中)
/*记住,模板的头文件中通常既包括声明也包括定义。函数模板和类模板成员函数的定义通常放在头文件中,不能分开放。。。。谨记*/#ifndef BLOB_H#define BLOB_H#include<iostream>#include<vector>#include<string>#include<memory>#include<initializer_list>using namespace std;template <typename> class BlobPtr;template <typename> class Blob;template <typename T>bool operator==(const Blob<T>&,const Blob<T>&);template <typename T>class Blob{friend class BlobPtr<T>;friend bool operator==<T> (const Blob<T>&,const Blob<T>&);public: typedef T value_type; typedef typename vector<T>::size_type size_type; Blob(); Blob(initializer_list<T> il); BlobPtr<T> begin() { return *this;} BlobPtr<T> end() { auto ret=BlobPtr<T>(*this,this->size()); return ret;} size_type size() const { return data->size();} bool empty() const { return data->empty();} void push_back(const T &t) { data->push_back(t);} void push_back(T &&t) { data->push_back(std::move(t));} void pop_back(); T& front(); T& back(); const T& front() const; const T& back() const; T& operator[](size_type i); const T& operator[](size_type i) const;private: shared_ptr<vector<T>> data; void check(size_type i,const string &msg) const;};template <typename T>Blob<T>::Blob(): data(std::make_shared<std::vector<T>>()) { }template<typename T>Blob<T>::Blob(initializer_list<T> il):data(make_shared<vector<T>>(il)) {}template<typename T>void Blob<T>::check(size_type i,const string &msg) const{ if(i>=data->size()) throw out_of_range(msg);}template<typename T>void Blob<T>::pop_back(){ check(0,"pop_back"); data->pop_back();}template <typename T>T& Blob<T>::front(){ check(0,"front"); return data->front();}template<typename T>T& Blob<T>::back(){ check(0,"back"); return data->back();}template<typename T>const T& Blob<T>::front() const{ check(0,"front"); return data->front();}template<typename T>const T& Blob<T>::back() const{ check(0,"back"); return data->back();}template<typename T>T& Blob<T>::operator[](size_type i){ check(i,"out_of_range"); return (*data)[i];}template<typename T>const T& Blob<T>::operator[](size_type i) const{ check(i,"out_of_range"); return (*data)[i];}template <typename T>bool operator==(const Blob<T> &lhs,const Blob<T> &rhs){ if(rhs.size()!=lhs.size()) return false; for(size_t i=0;i!=lhs.size();+i) if(lhs[i]!=rhs[i]) return false; return true;}template <typename T>ostream operator<<(ostream &os,const Blob<T> &a){ os<<"<"; for(size_t i=0;i!=a.size();++i) os<<a[i]<<" "; os<<">"; return os;}template <typename T>bool operator==(const BlobPtr<T>&,const BlobPtr<T>&);template <typename T> class BlobPtr{friend bool operator==<T> (const BlobPtr<T>&,const BlobPtr<T>&);public: BlobPtr():curr(0){} BlobPtr(Blob<T> &a,size_t sz=0):wptr(a.data),curr(sz){} T& operator*() const { auto p=check(curr,"dereference past end"); return (*p)[curr]; } BlobPtr& operator++(); BlobPtr& operator--(); BlobPtr& operator++(int); BlobPtr& operator--(int);private: shared_ptr<vector<T>> check(size_t,const string &) const; weak_ptr<vector<T>> wptr; size_t curr;};template <typename T>shared_ptr<vector<T>> BlobPtr<T>::check(size_t i,const string &msg) const{ auto ret=wptr.lock(); if(!ret) throw runtime_error("unbind BlobPtr"); if(i>=ret->size()) throw out_of_range(msg); return ret;}template <typename T>BlobPtr<T>& BlobPtr<T>::operator++(){ check(curr,"++"); ++curr; return *this;}template <typename T>BlobPtr<T>& BlobPtr<T>::operator--(){ --curr; check(curr,"--"); return *this;}template <typename T>BlobPtr<T>& BlobPtr<T>::operator++(int){ auto ret=*this; ++*this; return ret;}template <typename T>BlobPtr<T>& BlobPtr<T>::operator--(int){ auto ret=*this; --*this; return ret;}template <typename T>bool operator==(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs){ return (lhs.wptr.lock().get()==rhs.wptr.lock().get())&&lhs.curr==rhs.curr;}template <typename T>bool operator!=(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs){ return !(rhs==lhs);}#endif // BLOB_H
main.cpp
#include "Blob.h"int main(){ Blob<string> b1; // empty Blob cout << b1.size() << endl; { // new scope Blob<string> b2 = {"a", "an", "the"}; b1 = b2; // b1 and b2 share the same elements b2.push_back("about"); cout << b1.size() << " " << b2.size() << endl; } // b2 is destroyed, but the elements it points to must not be destroyed cout << b1.size() << endl; for(auto p = b1.begin(); p != b1.end(); ++p) cout << *p << endl; return 0;}
16.14 编写Screen类模板,用非类型参数定义Screen的高和宽。
16.15为你的Screen模板实现输入和输出运算符。Screen类需要哪些友元来令输入和输出运算符正确工作。
#include<iostream>#include <string>using namespace std;//模板非类型参数,友元一定要前置声明template <unsigned H,unsigned W>class Screen;template <unsigned H,unsigned W>ostream& operator<<(ostream &os,const Screen<H,W> &s);template <unsigned H,unsigned W>istream& operator>>(istream &is,Screen<H,W> &s);template <unsigned H,unsigned W>class Screen{friend ostream& operator<< <H,W> (ostream &os,const Screen<H,W> &s);friend istream& operator>> <H,W> (istream &is,Screen<H,W> &s);public: typedef string::size_type pos; Screen()=default; Screen(pos ht,pos wd,char c):height(ht),width(wd),contents(ht*wd,c){} char get() const { return contents[cursor]; } inline char get(pos ht,pos wd) const; Screen &move(pos r,pos c);private: pos cursor=0; pos height=H; pos width=W; string contents;};template<unsigned H,unsigned W>char Screen<H,W>::get(pos ht,pos wd) const{ pos row=ht*width; return contents[row+wd];}template <unsigned H,unsigned W>Screen<H,W>& Screen<H,W>::move(pos r,pos c){ pos row=r*width; cursor=row+c; return *this;}template <unsigned H,unsigned W>ostream& operator<<(ostream &os,const Screen<H,W> &s){ os<<s.cursor<<" "<<s.height<<" "<<s.width<<" "<<s.contents[s.cursor]<<endl; return os;}template <unsigned H,unsigned W>istream& operator>>(istream &is,Screen<H,W> &s){ is>>s.cursor>>s.height>>s.width>>s.contents; return is;}int main(){}
16.16
模板类之间的友元关系实现Blob和BlobPtr
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。