Snowming04's Blog
一颗红❤
Toggle navigation
Snowming04's Blog
主页
Cobalt Strike
Accelerated C++
区块链安全
友链
关于我
常用工具
代码积累
归档
标签
【Accelerated C++】课时15:再探字符图形
2020-04-19 08:44:03
458
0
0
snowming
``` //只有在执行的时候用到的私有类 //基类 class Pic_base{}; //四种具体的继承类 //客户直接给出的字符串的图形用String_Pic描述 class String_Pic:public Pic_base{}; //通过给某幅图形加框架生成的图形用Frame_Pic描述 class Frame_Pic:public Pic_base{}; //通过将两幅图形水平/垂直连接生成的图形用Hcat_Pic/Vcat_Pic描述 class Hcat_Pic:public Pic_base{}; class Vcat_Pic:public Pic_base{}; //公有接口类与操作 class Picture { public: Picture(const std::vector<std::string>& = std::vector<std::string>()); private: //在Picture类中我们将每一个操作通过Ptr类型对象转给底层的派生类型对象来实现该操作 Ptr<Pic_base> p; //指针类,管理引用计数以实现对基础对象的共享 }; ``` Picture类的接口: ``` Picture frame(const Picture&); Picture hcat(const Picture&, const Picture&); Picture vcat(const Picture&, const Picture&); std::ostream& operator<<(std::ostream&, const Picture&); ``` Pic_base类: ``` class Pic_base { //没有公有接口 typedef std::vector<std::string>::size_type ht_sz; //定义简写名字,表示图形的高度 typedef std::string::size_type wd_sz; //定义简写名字,表示图形的宽度 virtual wd_sz width() const =0; virtual ht_sz height() const =0; virtual void display(std::ostream&, ht_sz, bool) const =0; }; ```   ``` class Pic_base{ //没有公有接口 typedef std::vector<std::string>::size_type ht_sz; typedef std::string::size_type wd_sz; //这是个抽象基类 virtual wd_sz width() const=0; virtual ht_sz height() const=0; virtual void display(std::ostream&, ht_sz,bool) const=0; }; class Frame_Pic:public Pic_base { //不是一个抽象类 //没有公有接口 Ptr<Pic_base> p; Frame_Pic(const Ptr<Pic_base>& pic):p(pic){} //都是具体的函数 wd_sz width() const; ht_sz height() const; void display(std::ostream&, ht_sz, bool) const; }; ``` 其他派生类: ``` class Vcat_Pic:public Pic_base { Ptr<Pic_base> top,bottom; Vcat_Pic(const Ptr<Pic_base>& t, const Ptr<Pic_base>& b):top(t),bottom(b){} wd_sz width() const; ht_sz height() const; void display(std::ostream&, ht_sz, bool) const; }; class Hcat_Pic:public Pic_base { Ptr<Pic_base> left,right; HCat_Pic(const Ptr<Pic_base>& l, const Ptr<Pic_base>& r):left(l),right(r){} wd_sz width() const; ht_sz height() const; void display(std::ostream&, ht_sz, bool) const; }; ``` String_Pic类: ``` class String_Pic:public Pic_base { std::vector<std::string> data; String_Pic(const std::vector<std::string>& v):data(v){} wd_sz width() const; ht_sz height() const; void display(std::ostream&, ht_sz,bool) const; }; ``` ## 实现用户接口 ``` class Picture { public: Picture(const std::vector<std::string>&=std::vector<std::string>()); private: Ptr<Pic_base> p; Picture(Pic_base* ptr):p(ptr){} }; Picture frame(const Picture&); Picture hcat(const Picture&, const Picture&); Picture vcat(const Picture&, const Picture&); std::ostream& operator<<(std::ostream&, const Picture&); ``` ``` Picture frame(const Picture& pic) { return new Frame_Pic(pic.p); } ``` 上面这段代码等同于以下这段代码: ``` //生成一个新的Frame_Pic类型对象 Pic_base* templ=new Frame_Pic(pic.p); //用一个Pic_base*指针构造一个Picture类型对象 Picture temp2(temp1); //返回一个Picture类型对象,这将激活Picture类的复制构造函数 return temp2; ``` 另外两个连接函数: ``` Picture hcat(const Picture& l,const Picture& r) { return new HCat_Pic(l.p, r.p); } Picture vcat(const Picture& t,const Picture& b) { return new HCat_Pic(t.p, b.p); } ``` 用一个`vector<string>`类型对象来构造一个Picture类型对象: ``` Picture::Picture(const vector<string>& v):p(new String_Pic(v)){} ``` 输出运算符函数: ``` ostream& operator<<(ostream& os, const Picture& picture) { const Pic_base::ht_sz ht = picture.p -> height(); //遍历底层的Pic_base类型对象,然后调用display函数来显示每一行输出 for(Pic_base::ht_sz i=0; i!=ht; ++i) { picture.p->display(os,i,false); os<<endl; } return os; }; ``` ## String_Pic 类 ``` class String_Pic:public Pic_base { friend class Picture; std::vector<std::string> data; string_Pic(const std::vector<std::string>& v):data(v){} ht_sz height() const {return data.size();} wd_sz width() const; void display(std::ostream&, ht_sz, bool) const; }; ``` ``` Pic_base::wd_sz String_Pic::width() const { Pic_base::Wd_sz n=0; for(Pic_base::ht_sz i=0; i!=data.size();++i) n=max(n,data[i].size()); return n; } ``` ``` void String_Pic::display(ostream& os, ht_sz row, bool do_pad) const { wd_sz start = 0; //如果row没有超出范围,就输出第row行 if(row<height()) { os<<data(row); start=data[row].size(); } //如果必要的话补齐输出各行 if(do_pad) //pad函数带有三个参数:第一个参数是输出流;第二个参数是要补上空格的首位置;第三个参数是要补上空格的尾位置(后面的位置) pad(os,start,width()); } ```  补齐输出结果: ``` class Pic_base { //没有公有接口 typedef std::vector<std::string>::size_type ht_sz; typedef std::string::size_type wd_sz; //这是个抽象基类 virtual wd_sz width() const=0; virtual ht_sz height() const=0; virtual void display(std::ostream&, ht_sz,bool) const=0; protected: static void pad(std::ostream& os, wd_sz beg, wd_sz end) { while(beg!=end) { os<<" "; ++beg; } } }; ```  ## VCat_Pic类 连接图形的类: ``` class Vcat_Pic:public Pic_base { //友员函数vcat的友员声明 friend Picture vcat(const Picture&, const Picture&); Ptr<Pic_base> top, bottom; VCat_Pic(const Ptr<Pic_base>& t, const Ptr<Pic_base>& b):top(t),bottom(b){} //以内联子过程的方式实现height和width函数 wd_sz width() const {return max(top->width(),bottom->width());} ht_sz height() const {return top->height()+bottom->height();} void display(std::ostream&, ht_sz, bool) const; }; ``` display 函数: ``` void VCat_Pic::display(ostream& os, ht_sz row, bool do_pad) const { wd_sz w=0; if(row < top->height()) { //现在处于上面的子图形里 top->display(os,row,do_pad); w=top->width(); }else if(row<height()) { //现在处于下面的子图形里 bottom->display(os,row-top->height(),do_pad); w=bottom->width(); } if(do_pad) pad(os,w,width()); } ``` ## HCat_Pic类 ``` class HCat_Pic:public Pic_base { friend Picture hcat(const Picture&, const Picture&); Ptr<Pic_base> left, right; HCat_Pic(const Ptr<Pic_base>& l, const Ptr<Pic_base>& r):left(l),right(r){} wd_sz width() const {return left->width()+right->width();} ht_sz height() const{return max(left->height(),right->height());} void display(std::ostream&, ht_sz, bool) const; }; ``` ``` void HCat_Pic::display(ostream& os, ht_sz row, bool do_pad) const { left->display(os,row,do_pad||row< right->height()); right->display(os,row,do_pad); } ``` ## Frame_Pic类 这是一个派生类: ``` class Frame_Pic:public Pic_base { friend Picture frame(const Picture&); Ptr<Pic_base> p; Frame_Pic(const Ptr<Pic_base>& pic):p(pic){} wd_sz width() const {return p->width()+4;} ht_sz height() const {return p->height()+4;} void display(std::ostream&, ht_sz, bool) const; }; ``` display函数: ``` void Frame_Pic::display(ostream& os, ht_sz row, bool do_pad) const { if(row>height()) { //超出范围 if(do_pad) pad(os,0,width()); }else{ if(row==0||row==height()-1) { //在最顶行或者最底行 os<<string(width(),'*'); }else if(row==1||row==height()-2) { //在第二行或者倒数第二行 os<<"*"; pad(os,1,width()-1); os<<"*"; }else{ //在内部图形中 os<<"*"; p->display(os,row-2,true); os<<"*"; } } } ``` ## 友员类声明  ``` //对Picture类进行前置声明 class Picture; class Pic_base { friend std::ostream& operator<<(std::ostream&, const Picture&); friend class Frame_Pic; friend class HCat_Pic; friend class VCat_Pic friend class String_Pic; //没有公有接口 typedef std::vector<std::string>::size_type ht_sz; typedef std::string::size_type wd_sz; //这是个抽象基类 virtual wd_sz width() const=0; virtual ht_sz height() const=0; virtual void display(std::ostream&, ht_sz, bool) const=0; protected: static void pad(std::ostream& os, wd_sz, wd_sz); }; class Picture { friend std::ostream& operator<<(std::ostream&, const Picture&); friend Picture frame(const Picture&); friend Picture hcat(const Picture&, const Picture&); friend Picture vcat(const Picture&, const Picture&); public: Picture(const std::vector<std::string>&=std::vector<std::string>()); private: Picture(Pic_base* ptr):p(ptr){} Ptr<Pic_base> p; }; //对Picture类型对象进行操作 Picture frame(const Picture&); Picture hcat(const Picture&, const Picture&); Picture vcat(const Picture&, const Picture&); std::ostream& operator<<(std::ostream&, const Picture&); ``` ## 本章小结 **<u>抽象基类</u>**  **<u>前置声明</u>** 
上一篇:
实验使用 C 编译 shellcode 免杀上线
下一篇:
【Accelerated C++】课时14:近乎自动地管理内存
0
赞
458 人读过
新浪微博
微信
腾讯微博
QQ空间
人人网
提交评论
立即登录
, 发表评论.
没有帐号?
立即注册
0
条评论
More...
文档导航
没有帐号? 立即注册