本文将来解决这样一个问题:复制一个对象的意义是什么? #ifndef _GUARD_14_HANDLE_H_ #define _GUARD_14_HANDLE_H_ /******************************************************************** 创建时间: 2012/03/30 20:11 文件名称: 14_Handle.h 文件作者: jimacs ===================================================================== 功能说明: 一个封装的句柄类,与它管理的对象的类型完全无关 *********************************************************************/ #include <iostream> #include "core_grad.h" template <class T> class Handle { public: Handle():p(0) {} //默认构造函数 Handle(const Handle& s):p(0) { if (s.p) { p=s.p->clone(); } } Handle& operator= (const Handle& rhs) { if(&rhs!=this){ delete p; p=rhs.p ? rhs.p->clone():0; } return *this; } ~Handle() {delete p;} Handle(T* t):p(t) {} //单参数构造函数,与实际的对象绑定 operator bool () const {return p;} //类型转化操作符 T& operator*() const { if (p) { return *p; } throw runtime_error("unbond Handle"); } T* operator->() const{ if (p) { return p; } throw runtime_error("unbone Handle"); } //static bool compare_core_handles(const Handle& h1,const Handle& h2) //{ // return h1->name()<h2->name(); //} private: T* p; }; ////赋值操作符 //template <class T> //Handle<T>& Handle<T>::operator =(const Handle& rhs) //{ // if(&rhs!=this){ // delete p; // p=rhs.p ? rhs.p->clone():0; // } // return *this; //} // ////* //template <class T> //T& Handle<T>::operator * () const //{ // if (p) // { // return *p; // } // throw runtime_error("unbond Handle"); //} //template <class T> //T* Handle<T>::operator ->() const //{ // if (p) // { // return p; // } // throw runtime_error("unbone Handle"); //} #endif
#ifndef _GUARD_14_STUDENT_INFO_H_ #define _GUARD_14_STUDENT_INFO_H_ /******************************************************************** 创建时间: 2012/03/31 9:58 文件名称: 14_Student_info.h 文件作者: jimacs ===================================================================== 功能说明: 重新实现Student_info类,而handle作为纯粹的接口类,把管理 指针的工作委托给Handle类来实现 *********************************************************************/ #include <iostream> #include <stdexcept> #include "14_Handle.h" #include "core_grad.h" class Student_info { public: Student_info() {} Student_info(std::istream& is) {read(is);} //这里没有个函数,不需要了,都交给Handle类来完成 std::istream& read(std::istream&); //read std::string name() const { if (cp) { return cp->name(); } else { throw std::runtime_error("uninitialized student"); } } double grade() const { if (cp) { return cp->grade(); } else { throw std::runtime_error("uninitialized student"); } } static bool compare(const Student_info& s1,const Student_info& s2) { return s1.name()<s2.name(); } private: Handle<core> cp; }; #endif /******************************************************************** 创建时间: 2012/03/31 10:15 文件名称: 14_Student_info.cpp 文件作者: jimacs ===================================================================== 功能说明: 重新实现的Student_info类 --------------------------------------------------------------------- 其他说明: 被Handle接口类托管 *********************************************************************/ #include "14_Student_info.h" using namespace std; istream& Student_info::read(std::istream& is) { cout<<"Inter who('c'or other):"; char ch; is>>ch; if('c'==ch) { cp=new core(is); } else { cp=new grad(is); } return is; } //此函数与以前的Student_info函数相比,缺少了delete语句,为什么? //首先看new core(is)语句:首先我们会得到一个core*对象,然后我们使用Handle类 //的Handle(T*)构造函数来隐式的把他转化为Handle<core>类型的对象(对象),然后会使用 //Handle类的赋值操作符把这个对象赋值给Student_info中得cp(这个过程很复杂:因为 //赋值构造函数中有delete自动删除cp原先指向的对象,所以我们这里不需要delete;还有一点: //这里会调用赋值操作符中得conle函数,生成一个额外的指向原先core*对象的副本, //这个副本又会产生一个Handle<core>对象(对象))---这个额为的副本如何避免,引用计数句柄 /******************************************************************** 创建时间: 2012/03/30 21:01 文件名称: 14_Handle_main_1.cpp--主函数 文件作者: jimacs ===================================================================== 功能说明: 使用一个泛型句柄 --------------------------------------------------------------------- 其他说明: 14_Handle.h *********************************************************************/ #include <iostream> #include <string> #include <vector> #include <algorithm> #include <ios> #include <stdexcept> #include <iomanip> #include "14_Handle.h" #include "core_grad.h" using namespace std; static bool compare_core_handles(const Handle<core>& h1,const Handle<core>& h2) { return h1->name()<h2->name(); } int main() { vector< Handle<core> > student; Handle<core> record; char ch; string::size_type maxlen=0; while (cin>>ch) { if ('c'==ch) { record=new core; } else { record =new grad; } record->read(cin); maxlen=max(maxlen,record->name().size()); student.push_back(record); } //比较函数也可以作为handle类的静态函数,也可以作为全局函数,都可以 sort(student.begin(),student.end(),/*Handle<core>::*/compare_core_handles); for (vector< Handle<core> >::size_type i=0;i!=student.size();++i) { cout<<student[i]->name() <<string(maxlen+1-student[i]->name().size(),' '); try{ double final_grade=student[i]->grade(); streamsize pre=cout.precision(); cout<<setprecision(3) <<final_grade <<setprecision(pre)<<endl; }catch (domain_error e1){ cout<<e1.what()<<endl;} } return 0; } /******************************************************************** 创建时间: 2012/03/31 11:02 文件名称: 14_Student_info_main.cpp--主函数 文件作者: jimacs ===================================================================== 功能说明: 用新建的_Student_info头文件重新实现主函数 --------------------------------------------------------------------- 其他说明: Handle类管理底层数据 *********************************************************************/ #include <iostream> #include <vector> #include "14_Student_info.h" using namespace std; int main() { vector<Student_info> student; Student_info record; //同上面 return 0; }
#ifndef _GUARD_14_REF_HANDLE_CLASS_H_ #define _GUARD_14_REF_HANDLE_CLASS_H_ /******************************************************************** 创建时间: 2012/03/31 11:18 文件名称: 14_Ref_handle_class.h 文件作者: jimacs ===================================================================== 功能说明: 我们会为Ref_handle类添加一个指针来跟踪计数,Ref_handle所 指向的每个对象都会有一个相关的引用计数,来跟踪记录我们有多少个这个对象的副本 不管需不需要这个类都避免数据的复制 *********************************************************************/ #include <iostream> #include <stdexcept> template <class T> class Ref_handle { public: Ref_handle():p(0),refptr(new std::size_t(1)) { } Ref_handle(T* t):p(t),refptr(new std::size_t(1)) { } //三位一体 Ref_handle(const Ref_handle& h):p(h.p),refptr(h.refptr) { ++*retptr; } Ref_handle& operator=(const Ref_handle&); ~Ref_handle(); //as before Handle class operator bool () const {return p;} T& operator* () const { if (p) { return *p } throw runtime_error("unbound Ref_handle"); } T* operator->() const { if (p) { return p; } throw runtime_error("unbound Ref_handle"); } private: T* p; std::size_t* refptr; }; template <class T> Ref_handle<T> Ref_handle<T>::operator =(const Ref_handle& rhs) {//左操作数减之前,右操作数加。如果两个操作数指向同一个对象,这种做法即保证引用计数不变, //同时会保证引用计数不小心成为零。 ++*rhs.refptr; if (0==--*refptr) {//如果应用计数减后成为零,说明左操作数赋值前是指向底层对象的最后一个Ref_handle。 delete p; delete refptr; } p=rhs.p; refptr=rhs.refptr; return *this; } template <class T> Ref_handle<T>::~Ref_handle() { if (0==--*refptr) { delete p; delete refptr; } } #endif
#ifndef _GUARD_14_PTR_FINAL #define _GUARD_14_PTR_FINAL /******************************************************************** 创建时间: 2012/03/31 16:17 文件名称: 14_ptr(final handle).h 文件作者: jimacs ===================================================================== 功能说明: 最终的句柄类ptr,可以决定何时共享数据的句柄 *********************************************************************/ #include <iostream> template <class T> class Ptr { public: void make_unique() { if (*refptr != 1) { --*refptr; refptr = new std::size_t(1); //p=p?p->clone():0; //这里存在一个严重的问题,在Str_improvement中。 //因为clone只能作为类的成员函数。万一类中没有呢? p=p?clone(p):0; //中间函数来解决 } } Ptr():p(0),refptr(new std::size_t(1)) { } Ptr(T* t):p(t),refptr(new std::size_t(1)) { } Ptr(const Ptr& h):p(h.p),refptr(h.refptr) { ++*retptr; } Ptr& operator=(const Ptr&); ~Ptr(); //as before Handle class operator bool () const {return p;} T& operator* () const { if (p) { return *p } throw runtime_error("unbound Ref_handle"); } T* operator->() const { if (p) { return p; } throw runtime_error("unbound Ref_handle"); } private: T* p; std::size_t* refptr; }; template <class T> Ptr<T>& Ptr<T>::operator =(const Ptr& rhs) {//左操作数减之前,右操作数加。如果两个操作数指向同一个对象,这种做法即保证引用计数不变, //同时会保证引用计数不小心成为零。 ++*rhs.refptr; if (0==--*refptr) {//如果应用计数减后成为零,说明左操作数赋值前是指向底层对象的最后一个Ref_handle。 delete p; delete refptr; } p=rhs.p; refptr=rhs.refptr; return *this; } template <class T> Ptr<T>::~Ptr() { if (0==--*refptr) { delete p; delete refptr; } } template <class T> T* clone(const T* tp) { //通过这个函数来调用clone return tp->clone(); } //模板特化(template specialization) template <> Vec<char>* clone(const Vec<char>* vp) { return new Vec<char>(*vp); } #endif
#ifndef _GUARD_14_STR_IMPROVEMENT_H_ #define _GUARD_14_STR_IMPROVEMENT_H_ /******************************************************************** 创建时间: 2012/03/31 19:22 文件名称: 14_Str_improvement.h 文件作者: cjm ===================================================================== 功能说明: 原先Str类的一个改进,通过最终的句柄类Ptr *********************************************************************/ #include <iostream> #include <cstring> #include <algorithm> #include "14_ptr(final handle).h" #include "Vec.h" class Str { friend std::istream& operator >> (std::istream&,Str&); public: Str& operator+=(const Str& s) { data.make_unique(); std::copy(s.data->begin(),s.data->end(),std::back_inserter(*data)); return *this; } typedef Vec<char>::size_type size_type; Str():data(new Vec<char>) {} Str(const char* cp):data(new Vec<char>) { std::copy(cp,cp+std::strlen(cp),std::back_inserter(*data)); } Str(size_type n,char c):data(new Vec<char>(n,c)) {} template <class In> Str(In i,In j):data(new Vec<char>) { std::opy(i,j,std::back_inserter(*data)); } char& operator[](size_type i) { data.make_unique(); return(*data)[i]; } const char& operator[](size_type i) const { return (*data)[i]; } size_type size()const {return data->size();} private: Ptr< Vec<char> > data; }; std::ostream& operator<<(std::ostream& ,const Str&); Str operator+(const Str&,const Str&); #endif
template <class T> T* clone(const T* tp) { //通过这个函数来调用clone return tp->clone(); }
void make_unique() { if (*refptr != 1) { --*refptr; refptr = new std::size_t(1); //p=p?p->clone():0; //这里存在一个严重的问题,在Str_improvement中。 //因为clone只能作为类的成员函数。万一类中没有呢? p=p?clone(p):0; //中间函数来解决 } }
//模板特化(template specialization) template <> Vec<char>* clone(const Vec<char>* vp) { return new Vec<char>(*vp); }
#ifndef GUARE_CORE_GRAD_H #define GUARE_CORE_GRAD_H #include <iostream> #include <vector> #include <string> class core { friend class Student_info_handle; template <class T> friend class Handle; public: core():midterm(0.0),final(0.0) {}; //默认构造函数 core(std::istream& is) { read(is); }; //单参数构造函数 std::string name() const; //获得名字 virtual std::istream& read(std::istream&); //读取信息,虚函数 virtual double grade() const; //平均成绩,虚函数 virtual ~core() {} //虚的析构函数:可以用基类的指针销毁派生类的对象 private: std::string n; protected: std::istream& read_common(std::istream&); double midterm,final; std::vector<double> homework; //虚函数,克隆一个指针,创建一个对象:分配空间,使用core默认的复制构造函数来构造新对象 virtual core* clone() const { return new core(*this);} }; class grad:public core { public: grad():thesis(0.0) {}; grad(std::istream& is) { read(is); }; double grade( ) const; std::istream& read(std::istream&); protected: grad* clone() const { return new grad(*this); } private: double thesis; }; bool compare_new(const core& c1, const core& c2); //比较两个对象的name的大小,平常 bool compare_new_core_ptr(const core* c1,const core* c2); //重新定义比较函数,从而从引用变为指针的形式(非重载); bool compare_grades(const core& c1, const core& c2); //动态绑定 //bool compare_grades(core c1,core c2) //静态绑定到core::grade上(编译时就会绑定) //{ // return c1.grade()<c2.grade(); //} #endif #include "core_grad.h" #include "4_grade.h" #include "4_Student_info.h" #include <algorithm> using namespace std; //cord string core::name() const { return n; } double core::grade() const { return ::grade(midterm,final,homework); } istream& core::read_common(std::istream& in) { cout<<"输入学生姓名,期中,期末:"<<endl; in>>n>>midterm>>final; return in; } istream& core::read(std::istream& in) { read_common(in); read_hw(in,homework); return in; } //class grad istream& grad::read(istream& in) { read_common(in); //保护可以直接使用 cout<<"输入论文成绩:"<<endl; in>>thesis; read_hw(in,homework); //homework保护,可以直接使用 return in; } double grad::grade() const { return min(core::grade(),thesis); //这里生存空间操作符很重要,要不然就递归调用grad //版本的grade了。。。。。 } bool compare_new( const core& c1, const core& c2 ) /*比较两个对象的name的大小,平常*/ { return c1.name()<c2.name(); } bool compare_grades( const core& c1, const core& c2 ) /*动态绑定*/ { return c1.grade()<c2.grade();//怎么区分调用的事基类还是派生类中得grade呢,虚函数登场 } bool compare_new_core_ptr( const core* c1,const core* c2 ) /*重新定义比较函数,从而从引用变为指针的形式(侵卦兀?*/ { return compare_new(*c1,*c2); }
#ifndef __MEM__H #define __MEM__H #include<iostream> using namespace std; //自动管理内存块 typedef unsigned char byte; class Mem { private: byte* mem; int size; void ensureMinSize(int minSize); public: Mem(); Mem(int sz); ~Mem(); int msize(); //byte* pointer(); byte* pointer(int minSize=0); }; Mem::Mem() { mem =0; size =0; } Mem::Mem(int sz) { mem =0; size =0; ensureMinSize(sz); } Mem::~Mem() { delete []mem; } int Mem::msize() {//当前的内存大小 return size; } void Mem::ensureMinSize(int minSize) {//自动增长申请内存 if(size < minSize) { byte* newmem = new byte[minSize]; memset(newmem+size,0,minSize - size); memcpy(newmem,mem,size); delete []mem; mem = newmem; size = minSize; } } //byte* Mem::pointer() //{//返回当前内存的首地址 //return mem; //} byte* Mem::pointer(int minSize) {//重新增长内存并返回内存的起始地址 ensureMinSize(minSize); return mem; } #endif #include "mem.h" class Mystring { public: Mystring(); Mystring(char *str); ~Mystring(); void concat(char *str); void print(ostream &os); private: Mem *buf; }; Mystring::Mystring() { buf = 0; } Mystring::Mystring(char *str) { buf = new Mem(strlen(str)+1); strcpy((char*)buf->pointer(),str); } void Mystring::concat(char *str) { if(!buf) buf = new Mem; strcat((char*)buf->pointer(buf->msize()+strlen(str)),str); } void Mystring::print(ostream &os) { if(!buf) return ; os<<buf->pointer()<<endl; } Mystring::~Mystring() { delete buf; } void main() { Mystring s("mytest"); s.print(cout); s.concat(" is weikai"); s.print(cout); }
Mystring::Mystring(char *str) { if(! *str) { buf =0; return; } buf = new Mem(strlen(str)+1); strcpy((char*)buf->point(),str); } |