怎样实现图形多态显示?
比如说我有一个基类shape,它有两个虚函数draw()和move()功能,后来又从shape派生出来很多的其他的的基本图形类,比如说square,circle,ellipse等等,每一个类都重写了draw()和move(),我最终的目的是要在MFC程序的文档中存储绘制的图形列表,然后在视图中遍历图形列表,并显示出来,我应该怎么做?我所知道的就是,多态的显示可以这么做
//图形拖放
void dragAndDrop(shape& s) throw()//<-----一个多态函数
{
s.move(42,24);//<------动态绑定调用"合适的代码",绑定合适的派生图形
s.draw();//<只要是从shape派生来的类,都可以调用,就像可以预测未来一样
}当然了,这样简单的例子还行,一旦结合文档就麻烦了,为了记录每一个绘制的图形的数据,有必要建立一个列表.然后在视图中绘制的时候,遍历图形列表,使用图形多态显示.
多态的简单例子,可以参看 http://community.csdn.net/Expert/TopicView1.asp?id=3984730 中的部分内容.显示到还好说,基于前面的多态应用的例子就可以了,关键是在文档中存储每一种图形数据的时候,很麻烦.
你可以想象,每一个派生的基本图形需要记录的数据是不一样的(这个和它所拥有的成员变量有关),怎么样在DOC中记录这个图形列表也是一个难事,既然C++支持多态,我想的就是用多态的功能来实现,却不知道具体怎么实现多态序列化,又怎么在视图中调用多态显示.// shape.h: interface for the shape class.
//
//////////////////////////////////////////////////////////////////////#if !defined(AFX_SHAPE_H__79AFD738_5912_4037_91F0_32F03E4EBEDB__INCLUDED_)
#define AFX_SHAPE_H__79AFD738_5912_4037_91F0_32F03E4EBEDB__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000class shape
{
public:
shape(int x,int y) throw();
shape(const shape& s) throw();
virtual ~shape() throw();
virtual void draw()const throw()=0;
virtual void move(int x,int y) throw()=0;
protected:
int x_,y_;
void operator =(const shape& s) throw();
};=============================================
继承类,依稀记得代码来自C++ primier
class square : public shape
{
public:
virtual void move(int x,int y) throw();
virtual void draw() const throw();
square(int x,int y,int width) throw();
virtual ~square();
protected:
int width_;};
class circle : public shape
{
public:
virtual void move(int x,int y) throw();
virtual void draw() const throw();
circle(int x,int y,int radius);
virtual ~circle();protected:
int radius_;
};#endif // !defined(AFX_SHAPE_H__79AFD738_5912_4037_91F0_32F03E4EBEDB__INCLUDED_)/////////////很多代码就不列在这里了以前看过别人写的EastDraw,VCKBase有的下载,没有看过的人先去
http://www.vckbase.com/code/viewcode.asp?id=1627 下载一个回来自己看看先.作者实现的方法我感觉很笨拙,虽然管理起来也很方便,添加新的图形类也很方便,但是文档记录和图形显示没有利用多态性,使用了很多switch,添加了一个图形类,就要改动很多地方.他的代码这里分析一下:
基类CUnit,派生于CObject,实现了添加了Serialize支持,和自绘制(当然,都是虚函数)
派生类:
CDLine,CCurve,CRectangle,CRoundRectangle,CEllipse,CRound,CPolygon,CLiEllipse,CRoundArc,CEllipseArc,CPolyBezier,CText,都有自己的Serialize,和自己重新实现DrawXXX()函数这些都无可厚非,如果是我,我也会这么做的.
问题的关键在后面,看看他是怎么实现图形数据的记录和保存的:1,文档数据成员,使用了一个很长的,各种图形类的列表,如下
class CEastDrawDoc : public CDocument
{
protected: // create from serialization only
CEastDrawDoc();
DECLARE_DYNCREATE(CEastDrawDoc)// Attributes
public:
CObArray m_DLineArray;
CObArray m_CurveArray;
CObArray m_RectangleArray;
CObArray m_RoundRectangleArray;
CObArray m_EllipseArray;
CObArray m_RoundArray;
CObArray m_PolygonArray;
CObArray m_LiEllipseArray;
CObArray m_RoundArcArray;
CObArray m_EllipseArcArray;
CObArray m_PolyBezierArray;
CObArray m_TextArray;
省略......
}
2.序列化了,由上面的数据成员的定义,可以知道他只有下面的路走了:我下载的源代码中,没有序列化的代码,但是我猜想肯定是这样的:
void CEastDrawDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
//////我添加的
m_DLineArray.Serialize(ar);
m_CurveArray.Serialize(ar);
m_RectangleArray.Serialize(ar);
省略......
}
3.CEastDrawView::OnDraw(),代码中也没有实现,但是我想肯定是这样的:void CEastDrawView::OnDraw(CDC* pDC)
{
CEastDrawDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
///我添加的
// 一个循环
pDoc->m_DLineArray[i].DrawXXX(CDC*...);
pDoc->m_CurveArray[i].DrawXXX(CDC*...);
pDoc->m_RectangleArray[i].DrawXXX(CDC*...);
省略......
}诸位看官,看到这里你是否觉得作者这样的做法是否很好呢?我是不以为好的,但是不会说他差,只是觉得还有改进的地方.怎么改进,我这里也是和大家一起探讨,来实现图形的多态显示.所以就希望高人出来解决了!!解决只需要点拨关键的地方就可以了.我的做法是(全当作是抛砖引玉了):
文档数据存储
1.数据成员
// Attributes
public:
CTypedPtrList <CObList,CUnit *> m_UnitList;2.序列化
void CEastDrawDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
//保存图形列表
m_UnitList.Serialize(ar);
}
图形显示
3.视图显示
void CEastDrawView::OnDraw(CDC* pDC)
{
CEastDrawDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
///我添加的
// 一个循环
pDoc->m_UnitList[i].DrawXXX(CDC*...);
}/////////////////////////////////////
但是我不知道这里会不会有问题出现,首先是序列化,我不能够肯定它能否实现图形多态序列化(自动调用派生类的Serialize()函数),然后是视图显示,我也不能够保证它能否实现图形多态显示(自动调用派生类的DrawXXX()函数).到此,我的问题我才觉得讲清楚了,到底应该怎样实现图形多态序列化和图形多态显示,大侠们,显显身手吧!!!!!!!!!!!!!!
强烈召唤你们!!!!
比如说我有一个基类shape,它有两个虚函数draw()和move()功能,后来又从shape派生出来很多的其他的的基本图形类,比如说square,circle,ellipse等等,每一个类都重写了draw()和move(),我最终的目的是要在MFC程序的文档中存储绘制的图形列表,然后在视图中遍历图形列表,并显示出来,我应该怎么做?我所知道的就是,多态的显示可以这么做
//图形拖放
void dragAndDrop(shape& s) throw()//<-----一个多态函数
{
s.move(42,24);//<------动态绑定调用"合适的代码",绑定合适的派生图形
s.draw();//<只要是从shape派生来的类,都可以调用,就像可以预测未来一样
}当然了,这样简单的例子还行,一旦结合文档就麻烦了,为了记录每一个绘制的图形的数据,有必要建立一个列表.然后在视图中绘制的时候,遍历图形列表,使用图形多态显示.
多态的简单例子,可以参看 http://community.csdn.net/Expert/TopicView1.asp?id=3984730 中的部分内容.显示到还好说,基于前面的多态应用的例子就可以了,关键是在文档中存储每一种图形数据的时候,很麻烦.
你可以想象,每一个派生的基本图形需要记录的数据是不一样的(这个和它所拥有的成员变量有关),怎么样在DOC中记录这个图形列表也是一个难事,既然C++支持多态,我想的就是用多态的功能来实现,却不知道具体怎么实现多态序列化,又怎么在视图中调用多态显示.// shape.h: interface for the shape class.
//
//////////////////////////////////////////////////////////////////////#if !defined(AFX_SHAPE_H__79AFD738_5912_4037_91F0_32F03E4EBEDB__INCLUDED_)
#define AFX_SHAPE_H__79AFD738_5912_4037_91F0_32F03E4EBEDB__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000class shape
{
public:
shape(int x,int y) throw();
shape(const shape& s) throw();
virtual ~shape() throw();
virtual void draw()const throw()=0;
virtual void move(int x,int y) throw()=0;
protected:
int x_,y_;
void operator =(const shape& s) throw();
};=============================================
继承类,依稀记得代码来自C++ primier
class square : public shape
{
public:
virtual void move(int x,int y) throw();
virtual void draw() const throw();
square(int x,int y,int width) throw();
virtual ~square();
protected:
int width_;};
class circle : public shape
{
public:
virtual void move(int x,int y) throw();
virtual void draw() const throw();
circle(int x,int y,int radius);
virtual ~circle();protected:
int radius_;
};#endif // !defined(AFX_SHAPE_H__79AFD738_5912_4037_91F0_32F03E4EBEDB__INCLUDED_)/////////////很多代码就不列在这里了以前看过别人写的EastDraw,VCKBase有的下载,没有看过的人先去
http://www.vckbase.com/code/viewcode.asp?id=1627 下载一个回来自己看看先.作者实现的方法我感觉很笨拙,虽然管理起来也很方便,添加新的图形类也很方便,但是文档记录和图形显示没有利用多态性,使用了很多switch,添加了一个图形类,就要改动很多地方.他的代码这里分析一下:
基类CUnit,派生于CObject,实现了添加了Serialize支持,和自绘制(当然,都是虚函数)
派生类:
CDLine,CCurve,CRectangle,CRoundRectangle,CEllipse,CRound,CPolygon,CLiEllipse,CRoundArc,CEllipseArc,CPolyBezier,CText,都有自己的Serialize,和自己重新实现DrawXXX()函数这些都无可厚非,如果是我,我也会这么做的.
问题的关键在后面,看看他是怎么实现图形数据的记录和保存的:1,文档数据成员,使用了一个很长的,各种图形类的列表,如下
class CEastDrawDoc : public CDocument
{
protected: // create from serialization only
CEastDrawDoc();
DECLARE_DYNCREATE(CEastDrawDoc)// Attributes
public:
CObArray m_DLineArray;
CObArray m_CurveArray;
CObArray m_RectangleArray;
CObArray m_RoundRectangleArray;
CObArray m_EllipseArray;
CObArray m_RoundArray;
CObArray m_PolygonArray;
CObArray m_LiEllipseArray;
CObArray m_RoundArcArray;
CObArray m_EllipseArcArray;
CObArray m_PolyBezierArray;
CObArray m_TextArray;
省略......
}
2.序列化了,由上面的数据成员的定义,可以知道他只有下面的路走了:我下载的源代码中,没有序列化的代码,但是我猜想肯定是这样的:
void CEastDrawDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
//////我添加的
m_DLineArray.Serialize(ar);
m_CurveArray.Serialize(ar);
m_RectangleArray.Serialize(ar);
省略......
}
3.CEastDrawView::OnDraw(),代码中也没有实现,但是我想肯定是这样的:void CEastDrawView::OnDraw(CDC* pDC)
{
CEastDrawDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
///我添加的
// 一个循环
pDoc->m_DLineArray[i].DrawXXX(CDC*...);
pDoc->m_CurveArray[i].DrawXXX(CDC*...);
pDoc->m_RectangleArray[i].DrawXXX(CDC*...);
省略......
}诸位看官,看到这里你是否觉得作者这样的做法是否很好呢?我是不以为好的,但是不会说他差,只是觉得还有改进的地方.怎么改进,我这里也是和大家一起探讨,来实现图形的多态显示.所以就希望高人出来解决了!!解决只需要点拨关键的地方就可以了.我的做法是(全当作是抛砖引玉了):
文档数据存储
1.数据成员
// Attributes
public:
CTypedPtrList <CObList,CUnit *> m_UnitList;2.序列化
void CEastDrawDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
//保存图形列表
m_UnitList.Serialize(ar);
}
图形显示
3.视图显示
void CEastDrawView::OnDraw(CDC* pDC)
{
CEastDrawDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
///我添加的
// 一个循环
pDoc->m_UnitList[i].DrawXXX(CDC*...);
}/////////////////////////////////////
但是我不知道这里会不会有问题出现,首先是序列化,我不能够肯定它能否实现图形多态序列化(自动调用派生类的Serialize()函数),然后是视图显示,我也不能够保证它能否实现图形多态显示(自动调用派生类的DrawXXX()函数).到此,我的问题我才觉得讲清楚了,到底应该怎样实现图形多态序列化和图形多态显示,大侠们,显显身手吧!!!!!!!!!!!!!!
强烈召唤你们!!!!
解决方案 »
- Windows8下虚拟桌面无法创建成功的问题
- 关于线程性能统计时,线程里异步过程的具体执行时间会被计入到该线程的执行时间当中吗?
- 输出移动字符串出现的问题
- usbkey替换windows登录
- 请大家帮小弟参考一下!
- 我VC++.NET的调试输出窗口不见了!
- 怎样将在vc中完成的应用程序编译成可以在苹果电脑Mactosh操作系统运行的软件?
- 关于CFtpconnection,当putfile的时候如何终止?
- 多组控件,每组有相同的控件组成,有数据是判断是那组的数据进行相应显示,有图?可否将一数组绑定给控件?
- 请问逻辑坐标和设备坐标的区别?
- 我想做一个无界面的ACTIVEX,只要能完成复制文件、删除文件的操作就行了,我该如何做?
- 攻读计算机研究生的看法
我觉得还是增加一个中间的类比如CShapeManager,用来管理,序列化你的图形对象链表为好。
关于多态,深入浅出MFC中关于虚函数的章节有清晰的解释和用法
你的用法,m_UnitList.Serialize(ar);序列化可能没有问题,但是读出来就有问题了。
解决方法是在每次序列化一个对象前写入图形的标识,读取的时候由CShapsManager根据读出的标识,动态创建对象,再把ar传给这个对象完成读取。