C++沉思錄 第十章
阿新 • • 發佈:2019-02-19
練習需求:重新設計簡易版點陣圖,要求能通過靈活性的編寫程式碼滿足通過用字元代替二進位制資料在螢幕顯示滿足加框,佈局等需求.另外要能夠節約記憶體,不需要存放無用的資訊
我們用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: