概念
C++面向对象中的多态性是指同一种类型的对象在不同的情况下表现出不同的行为。
从代码层面看,实际上“同一种类型”就表明了,这里可以在循环里用相同的代码统一处理不同的功能。这一点很重要。
题目
界面上,拖动鼠标画矩形或者椭圆。
分析
先定义出矩形CShpRectangle和椭圆类CShpEllipse。因为要实现多态,还要先声明一个基类CShape,基类里有一个绘图功能Draw(),而且还得说明成虚函数,就是要“表现出不同的行为”。
这里用VC++代码,CObject是所有类的祖宗,所以都得从CObject继承过来。
class CShape : public CObject
{
public:
....
virtual void Draw(CDC* pDC)
{ TRACE("My Error: In CShape::Draw.\n");
ASSERT(FALSE); };
};
class CShpRectangle : public CShape
{
public:
void Draw(CDC* pDC); // Overrides CShape::Draw
};
class CShpEllipse : public CShape
{
public:
void Draw(CDC* pDC);
};
定义"不同的行为":
CShape中的Draw()是虚的,所以没功能可定义;
void CShpRectangle::Draw(CDC* pDC) // Virtual override
{
pDC->Rectangle(m_boxShape);//根据m_boxShape给的坐标开始画图
}
void CShpEllipse::Draw(CDC* pDC) // Virtual override
{
pDC->Ellipse(m_boxShape);
}
处理"不同的行为":
先定义一个基类指针 CShape* pShape; 再让这个指针指向它派生类的对象,这里实际有个强制类型转换,不然基类和派生类毕竟不是同一个类型,经过转换就是同一个类型了。
void CMyDrawView::OnDraw(CDC* pDC)
{......
CShape* pShape;
pDoc->SetToOldestShape();
while(pDoc->GetPos() != NULL)
{
pShape = pDoc->GetPrevShape();//GetPrevShape()函数就是做了一个强制转换(CShape*),先不用关注细节
pShape->Draw(pDC);
}
}
至此,多态的结构就结束了。其他代码都是各种附加功能:设置画笔风格、画矩形还是椭圆的切换、画的效果等等。
// Shape.h: interface for the CShape class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_SHAPE_H__97288485_7254_11D2_991B_00C04FC29F5C__INCLUDED_)
#define AFX_SHAPE_H__97288485_7254_11D2_991B_00C04FC29F5C__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
enum ShpType
{
shpRectangle,
shpEllipse
};
class CShape : public CObject
{
public:
// Enable MFC serialization (file storage for class objects)
DECLARE_SERIAL(CShape)
// Constructors and operators
// Default constructor
CShape();
// Copy constructor
CShape(const CShape& s)
{
m_boxShape = s.m_boxShape;
m_bTransparent = s.m_bTransparent;
m_nColorShape = s.m_nColorShape;
}
// Overloaded assignment operator
CShape& operator=(const CShape& s)
{
m_boxShape = s.m_boxShape;
m_bTransparent = s.m_bTransparent;
m_nColorShape = s.m_nColorShape;
return *this;
}
// Attributes - deliberately left public for easy access
// Note: no longer need an m_typeShape member.
CRect m_boxShape;
bool m_bTransparent;
UINT m_nColorShape;
// Overridables and operations
virtual void Draw(CDC* pDC)
{ TRACE("My Error: In CShape::Draw.\n");
ASSERT(FALSE); };
// Implementation
public:
virtual ~CShape();
};
// Concrete subclass of abstract base class CShape
class CShpRectangle : public CShape
{
public:
DECLARE_SERIAL(CShpRectangle)
// Constructors are inherited from CShape.
// Attributes inherited include:
// m_boxShape, m_bTransparent, m_nColorShape
// Operations
void Draw(CDC* pDC); // Overrides CShape::Draw
// Implementation
public:
};
// Concrete subclass of abstract base class CShape
class CShpEllipse : public CShape
{
public:
DECLARE_SERIAL(CShpEllipse)
// Constructors are inherited from CShape.
// Attributes inherited include:
// m_boxShape, m_bTransparent, m_nColorShape
// Operations
void Draw(CDC* pDC); // Overrides CShape::Draw
// Implementation
public:
};
#endif // !defined(AFX_SHAPE_H__97288485_7254_11D2_991B_00C04FC29F5C__INCLUDED_)
// DrawVw.h : interface of the CMyDrawView class
//
/////////////////////////////////////////////////////////////////////////////
#if !defined(AFX_DRAWVW_H__24958326_5D0A_11D2_991B_00C04FC29F5C__INCLUDED_)
#define AFX_DRAWVW_H__24958326_5D0A_11D2_991B_00C04FC29F5C__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "DrawDoc.h"
// Array of actual colors, indexed
// by CMyDrawView::m_nColorNext
static COLORREF arColors[10] =
{
RGB(0,0,0), // Black
RGB(0,0,255), // Blue
RGB(0,255,0), // Green
RGB(0,255,255), // Cyan
RGB(255,0,0), // Red
RGB(255,0,255), // Magenta
RGB(255,255,0), // Yellow
RGB(255,255,255), // White
RGB(128,128,128), // Dark gray
RGB(192,192,192) // Light gray
};
class CMyDrawView : public CView
{
protected: // create from serialization only
CMyDrawView();
DECLARE_DYNCREATE(CMyDrawView)
// Attributes
public:
CMyDrawDoc* GetDocument();
ShpType m_typeNext; // Type of CShape to draw next
CShape* m_pShpTemp; // The current CShape being drawn
bool m_bCaptured; // True if mouse has been captured
CBrush* m_pBrushOld; // Store brush for interior of shapes
bo