C++沉思录 第十章

练习需求:重新设计简易版位图,要求能通过灵活性的编写代码满足通过用字符代替二进制数据在屏幕显示满足加框,布局等需求.另外要能够节约内存,不需要存放无用的信息
我们用Picture类抽象成句柄满足各种图的多态性,通过句柄类Picture统一化管理。

Picture.h

#ifndef PICTURE_H
#define PICTURE_H
#include <ostream>
#include <P_Node.h>
#include <Frame.h>

using std::ostream;
using std::endl;

class Picture{
    friend ostream& operator <<(ostream& os,const Picture& p); 
public:
    Picture(const char* const * d,const int& r);
    Picture(const Picture& pic,const Frame& fra);
    Picture(const Picture& pic);
    Picture& operator=(const Picture& pic);
    char** cache();
    int getWidth() {return p->getWidth();}
    int getHeight() {return p->getHeight();}
    ~Picture();
private:
    P_Node* p;
};
#endif /*PICTURE_H*/

Picture.cpp

#include <picture.h>
#include <P_Node.h>
#include <iostream>
#include <Normal_Picture.h>
#include <Frame_Picture.h>

using std::ostream;


Picture::Picture(const char* const* d,const int& r) {
    p = new Normal_Picture(d,r);
}

Picture::Picture(const Picture& pic,const Frame& f) {
    p = new Frame_Picture(pic,f);
}
Picture::Picture(const Picture& pic) {
    ++(pic.p)->use;
    p = pic.p;
}

Picture& Picture::operator=(const Picture& pic) {
    ++(pic.p)->use;
    if (--p->use == 0) {
        delete p;
    }
    p = pic.p;
}

Picture::~Picture() {
    if (--p->use == 0) {
        delete p;
    }
}

ostream& operator<<(ostream& os,const Picture& pic) {
    pic.p->print(os);
    return os;
}
char** Picture::cache() {
    return p->cache();
}

我们通过P_Node指针统一管理所实现的各种位图

#ifndef P_NODE_H
#define P_NODE_H
#include <ostream>
using std::ostream;
class Picture;
class P_Node {
    friend class Picture;
public:
    P_Node():use(1){}
    virtual void print(ostream& os){}
    virtual char** cache(){}
    virtual ~P_Node();
protected:
    static int max(const int& a,const int& b) {return a > b ? a : b;}   
private:
    virtual int getWidth() {}
    virtual int getHeight() {}
    int use;
};
#endif /*P_NODE_H*/

P_Node.cpp

#include <P_Node.h>


P_Node::~P_Node() {
}

我们先来实现普通的位图 Normal_Picture.h

#ifndef NORMAL_PICTURE_H
#define NORMAL_PICTURE_H
#include <ostream>
#include <P_Node.h>
using std::ostream;

class Normal_Picture:public P_Node {
    friend ostream& operator <<(const ostream& os,const Picture& p);
public:
    Normal_Picture(const char* const* d,const int& r);
    ~Normal_Picture();
private:
    static int maxWidth(const char* const *d,const int& r);
    void print(ostream& os);
    void init(const char* const *d,const int& r);
    int getWidth() {return width;}
    int getHeight() {return height;}
    char** cache();
    char **data;
    int width;
    int height;
};
#endif /*NORMAL_PICTURE*/

Normal_Picture.cpp

#include <Normal_Picture.h>
#include <string.h>
using std::ostream;
using std::endl;
int Normal_Picture::maxWidth(const char* const* d,const int& r) {
    int mw = 0;
    for (int i = 0; i < r; ++i) {
        if (strlen(d[i]) > mw) {
            mw = strlen(d[i]);
        }
    }
    return mw;
}
void Normal_Picture::init(const char* const* d,const int& r) {
    width = Normal_Picture::maxWidth(d,r);  
    height = r;
    data = new char*[r];
    for (int i = 0; i < r; ++i) {
        data[i] = new char[strlen(d[i])];
        for (int j = 0; j < strlen(d[i]); ++j) {
            data[i][j] = d[i][j];
        }
    }   
}
Normal_Picture::Normal_Picture(const char* const* d,const int& r) {
    init(d,r);
}
char** Normal_Picture::cache() {
    char** temp = new char*[height];
    int j = 0;
    for (int i = 0; i < height; ++i) {
        temp[i] = new char[width];  
        for (j = 0; j < strlen(data[i]); ++j) {
            temp[i][j] = data[i][j];
        }
        while (j < width) {
            temp[i][j] = ' ';
            ++j;
        }
    }
    return temp;
}
void Normal_Picture::print(ostream& os) {
    char** temp = cache();
    for (int i = 0; i < height; ++i) {
        os << temp[i] << endl;
        delete []temp[i];
    }
    delete []temp;
}
Normal_Picture::~Normal_Picture() {
    for (int i = 0; i < height; ++i) {
        delete []data[i];
    }
    delete []data;
}

说明:我们通过cache(缓存)函数来辅助输出位图,通过位图类存放有用的信息,将缓存存放无用的空格,能够节约内存,通过其他位图类我们能看到他的优越性,更重要的是我们还能做到统一化管理.

接下来我们实现加框的位图
Frame_Picture.h

#ifndef FRAME_PICTURE_H
#define FRAME_PICTURE_H
#include <picture.h>
#include <Frame.h>
#include <ostream>
using std::ostream;
class P_Node;
class Frame_Picture:public P_Node {
    friend ostream& operator<< (ostream& os,const Picture& p);
    friend class Picture;
public:
    Frame_Picture(const Picture& pic,const Frame& fra);
    ~Frame_Picture() {}
private:
    void print(ostream& os);
    char** cache();
    int getWidth() {return p.getWidth() + 2;}
    int getHeight() {return p.getHeight() + 2;}
    Frame f;
    Picture p;
};
#endif /*FRAME_PICTURE_H*/

Frame_Picture.cpp

#include <P_Node.h>
#include <Frame_Picture.h>
#include <iostream>
using std::ostream;

Frame_Picture::Frame_Picture(const Picture& pic,const Frame& fra):p(pic),f(fra){}
char** Frame_Picture::cache() {
    char** temp = new char* [p.getHeight() + 2];
    char** c = p.cache();
    temp[0] = new char[p.getWidth() + 2];
    temp[p.getHeight() + 1] = new char[p.getWidth() + 2];
    for (int i = 1; i <= p.getHeight(); ++i) {
        temp[i] = new char[p.getWidth() + 2];
        for (int j = 1; j <= p.getWidth(); ++j) {
            temp[i][j] = c[i - 1][j - 1];
            temp[0][j] = f.getTop();
            temp[p.getHeight() + 1][j] = f.getBottom();
        }
        temp[i][0] = f.getLeft();
        temp[i][p.getWidth() + 1] = f.getRight();
    }
    temp[0][0] = f.getLeftTop();
    temp[0][p.getWidth() + 1] = f.getRightTop();
    temp[p.getHeight() + 1][0] = f.getLeftBottom();
    temp[p.getHeight() + 1][p.getWidth() + 1] = f.getRightBottom();
    return temp;
}
void Frame_Picture::print(ostream& os) {
    char** temp = cache();
    os << temp[0] << std::endl;
    for (int i = 1; i < getHeight(); ++i) {
        os << temp[i] << endl;;
        delete[] temp[i];
    }
    delete []temp;          
}

垂直布局和水平布局的类,我就偷懒不去实现了,实现也比较简单,

测试:

#include <picture.h>
#include <iostream>

using std::cout;
using std::endl;
int main() {
    char *init[] = {"Life is","Worth","Living"};
    Picture p(init,3);
    cout << p;
    Picture p2(p,Frame());
    cout << p2;
    Picture p3(p2,Frame());
    cout << p3;
}

接下来我们把编写的文件放在项目子目录src下
编写项目目录下的CMakeLists.txt文件:

project(PICTURE)
ADD_SUBDIRECTORY(src bin)

子目录src下编写CMakeLists,txt

SET(SRC_LIST "P_Node.h" "P_Node.cpp" "picture.h" "Picture.cpp" "Normal_Picture.h" "Normal_Picture.cpp" "Frame_Picture.h" "Frame_Picture.cpp" "Frame.h" "Frame.cpp")

ADD_LIBRARY(pic_shared SHARED ${SRC_LIST})
ADD_LIBRARY(pic_static STATIC ${SRC_LIST})

SET_TARGET_PROPERTIES(pic_shared PROPERTIES OUTPUT_NAME "pic" VERSION 1.0 SOVERSION 1.0)
SET_TARGET_PROPERTIES(pic_static PROPERTIES OUTPUT_NAME "pic")
INCLUDE_DIRECTORIES("/home/marco/cplus/proj3/src")
LINK_DIRECTORIES("/home/marco/cplus/proj3/build/bin")

ADD_EXECUTABLE(main "main.cpp")
TARGET_LINK_LIBRARIES(main "libpic.a")

项目子目录build进行cmake ..
make
执行main:

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值