本文已参与「新人创作礼」活动,一起开启掘金创作之路。
【C++】继承访问权限测试、友元类继承测试与多态性的综合运用
一、实验目的与要求
继承访问权限测试、友元类继承测试与多态性的综合运用
二、实验结果
1.初始图形
2.移动与复制后的图形
三、实验分析与总结
通过在Dev C++平台中对图形类CShape的实现,对继承与多态的编码方式与访问权限有了更加深入的了解。同时,还熟悉了友元类的定义与编码实现,能够更加方便的对相关类进行处理。
在实验中,为了能够更好的实现对于各个图形的操作设置了共有继承类例如CShape,而其他一些类例如CPoint、CTriangle与CRect通过public、protect与private这些方式继承了CShape。使得CPoint等这些派生类可以从基类CShape中获得其自身不曾定义过的成员,并且这让CPoint等类与基类CShape中的成员具有相同的属性,提高了我们的编程效率。
在实验过程中我们还使用了函数的重载,例如在CTriangle中将基类的GetArea与Draw等方法进行了重载,这样达到了一名多用的效果,让项目中相同作用的方法明朗直接的显示在我们眼前,使得所编写项目中的代码更加容易被理解。
在多态性方面,在实验中对输入输出完全一样的一般性多态函数做出了定义,例如virtual double GetArea();对于其他例如析构函数也做出了多态性说明,例如:virtual ~CShape()。
对于友元类,私有成员只能在类的成员函数内部访问,如果想在别处访问对象的私有成员,只能通过类提供的接口间接地进行。这固然能够带来数据隐藏的好处,利于将来程序的扩充,但也会增加程序书写的麻烦。因此我们设置了友元类,能够在类的成员函数外部直接访问对象的私有成员,很好的解决了编码麻烦的问题,同时也能够很好的对数据做出保护。
通过此次实验,对C++的相关知识有了更为深入的了解。通过在DevC++软件上的实验操作掌握了继承访问权限测试、友元类继承测试与多态性的综合运用与原理,为后续软件编程的学习打下了基础。
四、关键源代码
#include "graphics.h"
#include<iostream>
#include "CShape.h"
#include<vector>
using namespace std;
int main()
{
// 图形画布基础设置
initgraph(640, 480, INIT_RENDERMANUAL);//初始化显示一个窗口
setbkcolor(WHITE); //窗口背景颜色
setcolor(BLACK); //图形边框色
setfont(20, 0, "楷体");
setbkmode(TRANSPARENT); //绘图背景透明
vector<CShape*>shapes;
vector<CShape*>shapestmp;
shapes.push_back(new CTriangle(CPoint(450, 100), CPoint(400, 200), CPoint(500, 200))); //使用push.back尾部加入数据
// shapes.push_back(new CTriangle(CPoint(10, 10), CPoint(150, 10), CPoint(150, 150)));
shapes.push_back(new CRect(CPoint(250, 100), CPoint(350, 200)));
shapes.push_back(new CRecTri(CRect(CPoint(100, 100), CPoint(200, 200))));
//移动
bool move_flag = false;
bool copy_flag = false;
bool redraw = true;
//鼠标点击时记录它的坐标
int clickX, clickY;
int copyX, copyY;
int checkedid = -1;
int copyid = -1;
for (; is_run(); delay_fps(60)) { //循环,is_run判断窗口是否还在,delay_fps是延时
while (mousemsg()) { //获取鼠标消息,这个函数会等待,等待到有消息为止
mouse_msg msg = getmouse();
//判断鼠标的移动
if (msg.is_move()) {
if (checkedid != -1) {
if (move_flag) {
shapes[checkedid]->Move(msg.x - clickX, msg.y - clickY);
}
}
clickX = msg.x;
clickY = msg.y;
redraw = true;
}
// 判断鼠标左键
else if (msg.is_left()) {
// 判断鼠标左键是否按下
if (msg.is_down()) {
clickX = msg.x;
clickY = msg.y;
CPoint pt = CPoint(clickX, clickY);
int isIn = 0;
for (int i = 0; i < shapes.size(); i++) {
if (shapes[i]->ptIn(pt)) {
isIn = 1;
//如果鼠标在图形区域内就设置移动的flag为true
move_flag = true;
checkedid = i;
redraw = true;
break;
}
}
if (isIn == 0)
checkedid = -1;
}
else {
move_flag = false;
}
}
}
// 重新绘图
if (redraw) {
redraw = false;
cleardevice();
for (int i = 0; i < shapes.size(); i++) {
if (i == checkedid)
shapes[i]->DrawBlue();
else
shapes[i]->Draw();
}
}
while (kbmsg()) {
key_msg msgk = getkey();
if (msgk.key == key_A && msgk.msg == key_msg_down) {
mouse_msg msgm = getmouse();
if (msgm.is_left()) {
// 判断鼠标左键是否按下
if (msgm.is_down()) {
shapes.push_back(new CRect(CPoint(msgm.x, msgm.y)));
redraw=true;
}
}
if (msgm.is_right()) {
// 判断鼠标右键是否按下
if (msgm.is_down()) {
shapes.push_back(new CTriangle(CPoint(msgm.x, msgm.y)));
redraw=true;
}
}
}
if (msgk.key == key_Z && msgk.msg == key_msg_down) {
mouse_msg msgm = getmouse();
if (msgm.is_left()) {
// 判断鼠标左键是否按下
if (msgm.is_down()) {
copyX = msgm.x;
copyY = msgm.y;
CPoint pt = CPoint(copyX, copyY);
for (int i = 0; i < shapes.size(); i++) {
if (shapes[i]->ptIn(pt)) {
//如果鼠标在图形区域内就设置移动的flag为true
copy_flag = true;
copyid = i;
break;
}
}
}
}
if (msgm.is_right()) {
// 判断鼠标右键是否按下
if (msgm.is_down()) {
if (copy_flag == true) {
shapes.push_back(&(shapes[copyid]->Clone())->Move(msgm.x-copyX,msgm.y-copyY));
redraw = true;
}
}
}
}
}
}
closegraph();
return 0;
}