《C++沉思录:Ruminations on C++》Picture类

// Picture.h
#include <iostream>
using namespace std;

// 类声明
class P_Node; 
class Picture; 

//==============================================================================
/// global function
//==============================================================================
Picture frame(const Picture&);

//==============================================================================
/// class Picture
//==============================================================================
class Picture
{
	friend ostream& operator<<(ostream&, const Picture&);
	friend Picture reframe(const Picture&, char, char, char);

public:
	Picture();
	Picture(P_Node*);
	Picture(const Picture&);
	Picture(const char* const*, int);
	~Picture();

	int height()const;
	int width()const;
	void display(ostream&, int, int)const;

	Picture& operator=(const Picture&);

private:
	P_Node* p; // 使用父类类型,方便不同的类型进行使用

};

//==============================================================================
/// class P_Node
//==============================================================================
class P_Node
{
	friend Picture;

protected:
	P_Node();
	virtual ~P_Node();

	int max(int x, int y) const;

	virtual void display(ostream&, int, int)const = 0; // 子类必须实现的方法,函数中操作的都是const成员变量 
	virtual int height()const = 0; // 为子类添加必须实现的方法,函数中操作的都是const成员变量
	virtual int width()const = 0;  // 为子类添加必须实现的方法,函数中操作的都是const成员变量

public:
	virtual Picture doreframe(char, char, char) = 0;  // 为子类添加必须实现的方法,函数中操作的都是const成员变量

	int refcount;
};

//==============================================================================
/// class String_Pic
//==============================================================================
class String_Pic: public P_Node
{
	friend Picture;

public:
	String_Pic(const char* const*, int);
	~String_Pic();

	void display(ostream&, int, int)const;
	int height()const; 
	int width()const;  
	Picture doreframe(char, char, char);

private:
	char** data;
	int size;
	int h; 
	int w; 

};

//==============================================================================
/// class Frame_Pic
//==============================================================================
class Frame_Pic: public P_Node
{
	friend Picture;
	friend Picture frame(const Picture&);
	friend Picture reframe(const Picture&, char, char, char);

public:
	Frame_Pic();
	Frame_Pic(const Picture&, char = '+', char = '|', char = '-');

	void display(ostream&, int, int)const;
	int height()const; 
	int width()const;  
	Picture doreframe(char, char, char);

private:
	Picture p;
	char corner;
	char sideborder;
	char topborder;

};

//==============================================================================
/// class Vcat_Pic
//==============================================================================
class Vcat_Pic: public P_Node
{
	friend Picture;
	friend Picture operator&(const Picture&, const Picture&);
	friend Picture reframe(const Picture&, char, char, char);

public:
	Vcat_Pic(const Picture&, const Picture&);

	void display(ostream&, int, int)const;
	int height()const; 
	int width()const;  
	Picture doreframe(char, char, char);

private:
	Picture top, bottom;

};

//==============================================================================
/// class Hcat_Pic
//==============================================================================
class Hcat_Pic: public P_Node
{
	friend Picture;
	friend Picture operator|(const Picture&, const Picture&);
	friend Picture reframe(const Picture&, char, char, char);

public:
	Hcat_Pic(const Picture&, const Picture&);

	void display(ostream&, int, int)const;
	int height()const; 
	int width()const;  
	Picture doreframe(char, char, char);

private:
	Picture left, right;

};
// Picture.cpp
#include "Picture.h"

//==============================================================================
/// global function
//==============================================================================
static void pad(ostream& out, int x, int y)
{
	for(int i = x; i < y; ++i)
	{
		out<<" ";
	}
}

ostream& operator<<(ostream& os, const Picture& p)
{
	for(int i = 0; i < p.height(); ++i)
	{
		p.display(os, i, p.width());
		os<<endl;
	}

	return os;
}

Picture frame(const Picture& pic) 
{
	return new Frame_Pic(pic);
}

Picture reframe(const Picture& pic, char c, char s, char t)
{
	return pic.p->doreframe(c, s, t);
}

Picture operator&(const Picture& top, const Picture& bottom)
{
	return new Vcat_Pic(top, bottom);
}

Picture operator|(const Picture& right, const Picture& left)
{
	return new Hcat_Pic(right, left);
}

//==============================================================================
/// class Picture
//==============================================================================
Picture::Picture(P_Node* pnode)
:p(pnode)
{
}

Picture::Picture(const char* const* str, int size)
:p(new String_Pic(str, size))
{
}

Picture::Picture(const Picture& ori) 
{
	p = ori.p;
	p->refcount++;
}

Picture& Picture::operator=(const Picture& ori)
{
	ori.p->refcount++;
	if(--p->refcount == 0)
	{
		delete p;
		p = NULL;
	}
	p = ori.p;

	return *this;
}

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

int Picture::height() const
{
	return p->height();
}

int Picture::width()const
{
	return p->width();
}


void Picture::display(ostream& out, int x, int y)const
{
	p->display(out, x, y);
}

//==============================================================================
/// class P_Node
//==============================================================================
P_Node::P_Node()
:refcount(1)
{
}

P_Node::~P_Node()
{
}

int P_Node::max(int x, int y)const
{
	return x > y ? x : y;
}

//==============================================================================
/// class String_Pic
//==============================================================================
String_Pic::String_Pic(const char* const* p, int n)
:size(n)
{
	int i = 0;
	w = 0;
	for(i = 0; i < size; ++i)
	{
		w = max(w, static_cast<int>(strlen(p[i])));
	}
	h = size;

	data = new char*[size];
	for(i = 0; i < size; ++i) 
	{
		data[i] = new char[strlen(p[i]) + 1];
		strcpy_s(data[i], strlen(p[i]) + 1, p[i]);
	}
}

String_Pic::~String_Pic()
{
	for(int i = 0; i < size; ++i) 
	{
		delete[] data[i];
		data[i] = NULL;
	}

	delete data;
	data = NULL;
}

void String_Pic::display(ostream& out, int row, int width)const
{
	int start = 0;
	if((row >= 0) && (row < height()))
	{
		out<<data[row];
		start = strlen(data[row]);
	}

	pad(out, start, width);
}

int String_Pic::height()const 
{
	return h;
}

int String_Pic::width()const 
{
	return w;
}

Picture String_Pic::doreframe(char c , char s, char t)
{
	++refcount;
	return this;
}

//==============================================================================
/// class Frame_Pic
//==============================================================================
Frame_Pic::Frame_Pic(const Picture& picture, char c, char s, char t)
:p(picture), corner(c), sideborder(s), topborder(t)
{
}

void Frame_Pic::display(ostream& out, int row, int wd)const
{
	if((row < 0) || (row >= height()))
	{
		pad(out, 0, wd);
	}
	else 
	{
		if((row == 0) || (row == (height() - 1)))
		{
			out<<corner; //out << "+";
			int i = p.width();
			while(--i >= 0) 
			{
				out<<topborder; //out << "-";
			}
			out<<corner; //out << "+";
		}
		else 
		{
			out<<sideborder; //out << "|";
			p.display(out, row - 1, p.width());
			out<<sideborder; //out << "|";
		}
		pad(out, width(), wd);
	}
}

Picture Frame_Pic::doreframe(char c, char s, char t)
{
	return new Frame_Pic(reframe(this->p, c, s, t), c, s, t);
}

int Frame_Pic::height()const
{
	return (p.height() + 2);
}

int Frame_Pic::width()const
{
	return (p.width() + 2);
}

//==============================================================================
/// class Vcat_Pic
//==============================================================================
Vcat_Pic::Vcat_Pic(const Picture& t, const Picture& b)
:top(t), bottom(b)
{
}

void Vcat_Pic::display(ostream& out, int row, int wd)const
{
	if((row >= 0) && (row < top.height()))
	{
		top.display(out, row, wd);
	}
	else if((row < top.height()) + bottom.height())
	{
		bottom.display(out, row - top.height(), wd);
	}
	else 
	{
		pad(out, 0, wd);
	}
}

int Vcat_Pic::height()const
{
	return (top.height() + bottom.height());
}

int Vcat_Pic::width()const 
{
	return max(top.width(), bottom.width());
}

Picture Vcat_Pic::doreframe(char c, char s, char t)
{
	return new Vcat_Pic(reframe(top, c, s, t), reframe(bottom, c, s, t));
}

//==============================================================================
/// class Hcat_Pic
//==============================================================================
Hcat_Pic::Hcat_Pic(const Picture& l, const Picture& r)
:left(l), right(r)
{
}

void Hcat_Pic::display(ostream& out, int row, int wd)const
{
	left.display(out, row, left.width());
	right.display(out, row, right.width());
	pad(out, width(), wd);
}

Picture Hcat_Pic::doreframe(char c, char s, char t)
{
	return new Hcat_Pic(reframe(left, c, s, t), reframe(right, c, s, t));
}

int Hcat_Pic::height()const
{
	return max(left.height(), right.height());
}

int Hcat_Pic::width()const
{
	return (left.width() + right.width());
}
// main.cpp
#include "Picture.h"

int main(int argc, char* const argv[]) 
{
	char* characters[] = {"Hello,", "World!"};

	Picture p(characters, sizeof(characters) / sizeof(characters[0]));
	cout<<p<<endl;

	Picture q = frame(p);
	cout<<q<<endl;

	Picture r = p | q;
	cout<<r<< endl;

	Picture s = q & r;
	cout<<s<<endl<<frame(s)<<endl;

	cout<<reframe(frame(s), '*', '@', '#')<<endl;

	cout<<"Press any key to continue ......"<<endl;
	getchar();

	return 0;
}
输出:
Hello,
World!

+------+
|Hello,|
|World!|
+------+

Hello,+------+
World!|Hello,|
      |World!|
      +------+

+------+
|Hello,|
|World!|
+------+
Hello,+------+
World!|Hello,|
      |World!|
      +------+

+--------------+
|+------+      |
||Hello,|      |
||World!|      |
|+------+      |
|Hello,+------+|
|World!|Hello,||
|      |World!||
|      +------+|
+--------------+

*##############*
@*######*      @
@@Hello,@      @
@@World!@      @
@*######*      @
@Hello,*######*@
@World!@Hello,@@
@      @World!@@
@      *######*@
*##############*

Press any key to continue ......
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值