1, Inheritance access test
1.1 experimental contents
Design member functions or variables of class A with different attributes such as public, protected and private;
Class B inherits A through public, protected, private and other ways, and tests the member function or variable accessing A in the member function of class B;
Add member functions or variables with different attributes such as public, protected and private to class B, and test and access each member function or variable of B externally;
B inherits A in A private way and tries to promote some public members in A to public.
1.2 implementation code
#include<iostream> using namespace std; class A{ public: int a=0; protected: int b=0; private: int c=0; }; class Pub_B: public A{ public: void show1( ){ a=1; cout<<"Pub_B Can access a="<<a<<endl; } void show2( ){ b=1; cout<<"Pub_B Can access b="<<b<<endl; } /* void show3( ){ c=1; cout<<"Pub_B You can access C = "< < C < < endl; }Inaccessible*/ int b1; protected: int b2; private: int b3; }; class Pro_B: protected A{ public: void show1( ){ a=2; cout<<"Pro_B Can access a="<<a<<endl; } void show2( ){ b=2; cout<<"Pro_B Can access b="<<b<<endl; } /* void show3( ){ c=2; cout<<"Pro_B You can access C = "< < C < < endl; }Inaccessible*/ int bb1; protected: int bb2; private: int bb3; }; class Pri_B: private A{ public: void show1( ){ a=8; cout<<"Pri_B Can access a="<<a<<endl; } void show2( ){ b=8; cout<<"Pri_B Can access b="<<b<<endl; } /* void show3( ){ c=8; cout<<"Pri_B You can access C = "< < C < < endl; }Inaccessible*/ using A::a; //Promote a to public, which can be accessed int bbb1; protected: int bbb2; private: int bbb3; }; class newPri_B: private Pri_B{ public: void show1( ){ // a is promoted to public and can be accessed a=28; cout<<"newPri_B Can access a="<<a<<endl; } /* void show2( ){ b=28; cout<<"newPri_B You can access B = "< < B < < endl; }Inaccessible */ /* void show3( ){ c=28; cout<<"newPri_B You can access C = "< < C < < endl; } Inaccessible */ protected: private: }; int main() { Pub_B aa; aa.show1(); aa.show2(); //External access to public_b class variables and member functions, only public can access aa.b1; //aa.b2 is not accessible //aa.b3 not accessible //aa.show3(); not accessible Pro_B bb; bb.show1(); bb.show2(); //bb.show3(); not accessible Pri_B cc; cc.show1(); cc.show2(); //cc.show3(); not accessible newPri_B dd; dd.show1(); // a is promoted to public and can be accessed //dd.show2(); not accessible //dd.show3(); not accessible return 0; }
1.3 operation results
2, Friend class inheritance test
2.1 experimental contents
Design Class A contains private variable a, and friends in class A are given to class C;
Design class B to inherit a and add private variable B; test and access member variables A and B of class B in class C;
Design Class D to inherit C, test and access the member variables a of class A and a and B of class B in the member function of D.
2.2 implementation code
#include<iostream> using namespace std; class A { private: int a=1; friend class C; }; class B: public A { private: int b=2; }; class C { public: int c=8; void show() { B bb; cout<<"class C Can access a="<<bb.a<<endl; //Cout < < "class C can be accessed to get b =" < < BB. B < < endl; not accessible } }; class D :public C { public: void show() { cout<<"class D Can access c="<<c<<endl; A a1; //Cout < < "class D can be accessed to get a =" < < A1. A < < endl; not accessible B b1; //Cout < < class D can be accessed to get a = "< < B1. A < < endl; not accessible //Cout < < "class D can be accessed to get b =" < < B1. B < < endl; not accessible } }; int main(){ C cc; cc.show(); D dd; dd.show(); return 0; }
2.3 operation results
3, Comprehensive application of polymorphism
3.1 experimental contents
General polymorphism function: the input and output parameters are exactly the same, and virtual is added to the parent class;
Special polymorphism function: the input or output parameters are the pointer of the parent class or the reference of the base class in the subclass, and the pointer of the subclass or the reference of the subclass in the subclass;
Polymorphism of destructor;
Multi inheritance, pay attention to what needs virtual inheritance;
3.2 general polymorphic functions
Create a new CVehicle class. Move() is its internal virtual function. Create a new CCar class, CBicycle class and CMaglevTrain class to inherit CVehicle class, and rewrite the implementation method of its internal function move() to achieve polymorphic effect.
3.2.1 implementation code
#include <iostream> using namespace std; class CVehicle { public: CVehicle() { m_nWheels = 8; } CVehicle(int nWheel) { m_nWheels = nWheel; } void Move() { cout << "Vehicle has many Wheels" << endl; }; protected: int m_nWheels; }; class CCar : virtual public CVehicle { public: CCar() { m_nWheels = 4; } CCar(int nWheels) { m_nWheels = nWheels; } void Move() { cout << "Car has four Wheels" << endl; }; }; class CBicycle :virtual public CVehicle { public: CBicycle() { m_nWheels = 2; } CBicycle(int nWheels) { m_nWheels = nWheels; } void Move() { cout << "Bicycle has two Wheels" << endl; }; }; class CMaglevTrain : public CCar, public CBicycle { public: //non-parameter constructor CMaglevTrain() { m_nWheels = 0; } CMaglevTrain(int nWheels) { m_nWheels = nWheels; } void Move() { cout << "MaglevTrain has no Wheels" << endl; } }; void TestVehicle() { CVehicle* Vehicle[4]; Vehicle[0] = new CVehicle; Vehicle[1] = new CCar; Vehicle[2] = new CBicycle; Vehicle[3] = new CMaglevTrain; for(int i = 0; i < 4; i++) { Vehicle[i]->Move(); } } int main() { TestVehicle(); return 0; }
3.2.2 operation results
3.3 special polymorphic functions
In order for each subclass to output the function Move rewritten in its own class, we need to add virtual before the Move function of the parent class of each subclass.
3.3.1 implementation code
void callMove(CVehicle* a) { a->Move(); } void TestVehicle() { CVehicle vehicle; CCar car; CBicycle bicycle; CMaglevTrain maglev_train; callMove(&vehicle); callMove(&car); callMove(&bicycle); callMove(&maglev_train); }
3.3.2 operation results
3.4 polymorphism of destructor
Design vector graphics, using multi inheritance design combination graphics, requires the ability to create different types of vector graphics, select graphics, move graphics, display graphics with different colors (indicating whether it is selected or not), and manage graphics with vector or array.
3.4.1 implementation code
Main.cpp
#include<vector> #include "graphics.h" #include<iostream> #include "CShape.h" using namespace std; int main() { //Graphics canvas basic settings initgraph(640, 480); setbkcolor(WHITE); delay_ms(0); setcolor(BLACK); setfont(20, 0, "Regular script"); setbkmode(TRANSPARENT); //enter + left click -- > new rectangle ""); //enter + right click -- > New Triangle ""); //enter + middle of scroll wheel -- > new composite graphics //ctrl + left click -- > copy graphic ""); //ctrl + right click -- > Paste graphic ""); vector<CShape*>shapes; vector<CShape*>shapestmp; shapes.push_back(new CTriangle(CPoint(320, 320), CPoint(250, 340), CPoint(340, 450))); //shapes.push_back(new CTriangle(CPoint(10, 10), CPoint(150, 10), CPoint(150, 150))); shapes.push_back(new CRect(CPoint(200, 200), CPoint(300, 300))); shapes.push_back(new Comgraphics(CRect(CPoint(250, 50)))); //move bool move_flag = false; bool copy_flag = false; bool redraw = true; //Record its coordinates when the mouse clicks int clickX, clickY; int copyX, copyY; int checkedid = -1; int copyid = -1; for (; is_run(); delay_fps(60)) { while (mousemsg()) { mouse_msg msg = getmouse(); //Judge the movement of the mouse 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; } // Left mouse button else if (msg.is_left()) { // Judge whether the left mouse button is pressed 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; //If the mouse is in the graphics area, set the moving flag to true move_flag = true; checkedid = i; redraw = true; break; } } if (isIn == 0) checkedid = -1; } else { move_flag = false; } } } // Redrawn if (redraw) { redraw = false; cleardevice(); for (int i = 0; i < shapes.size(); i++) { if (i == checkedid) shapes[i]->DrawColor(); else shapes[i]->Draw(); } } while (kbmsg()) { key_msg msgk = getkey(); if (msgk.key == key_enter && msgk.msg == key_msg_down) { mouse_msg msgm = getmouse(); if (msgm.is_left()) { // Judge whether the left mouse button is pressed if (msgm.is_down()) { shapes.push_back(new CRect(CPoint(msgm.x, msgm.y))); redraw = true; } } if (msgm.is_right()) { // Judge whether the right mouse button is pressed if (msgm.is_down()) { shapes.push_back(new CTriangle(CPoint(msgm.x, msgm.y))); redraw = true; } } if (msgm.is_mid()) { CRect r1 = CRect(CPoint(msgm.x, msgm.y)); // Determine whether the middle mouse button is pressed if (msgm.is_down()) { shapes.push_back(new Comgraphics(r1)); redraw = true; } } } if (msgk.key == key_control && msgk.msg == key_msg_down) { mouse_msg msgm = getmouse(); if (msgm.is_left()) { // Judge whether the left mouse button is pressed 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)) { //If the mouse is in the graphics area, set the moving flag to true copy_flag = true; copyid = i; break; } } } } if (msgm.is_right()) { // Judge whether the right mouse button is pressed 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; }
CShape.h
#ifndef CSHAPE_H #define CSHAPE_H #include<string> #include<math.h> using namespace std; class CPoint; class CRect; class CShape { public: CShape(); CShape(const CShape& shape); virtual ~CShape(); virtual double GetArea() const; virtual bool ptIn(const CPoint& pt) const; virtual bool InRect(const CRect& rc) const; virtual void Draw() const; virtual void DrawColor(); virtual CShape* Clone() const; virtual CShape& Move(int nOffsetX, int nOffsetY); protected: string m_sName; }; class CPoint :public CShape { public: int m_nPosX; int m_nPosY; CPoint() { m_nPosX = 0; m_nPosY = 0; } CPoint(int nPosX, int nPosY); CPoint(const CPoint& pt); virtual ~CPoint(); double GetArea() const; bool ptIn(const CPoint& pt) const; bool InRect(const CRect& rc) const; void Draw() const; void DrawColor(); CPoint* Clone() const; CPoint& Move(int nOffsetX, int nOffsetY); }; class CTriangle :virtual public CShape { public: CTriangle() {} CTriangle(const CPoint& pt1, const CPoint& pt2, const CPoint& pt3); CTriangle(const CTriangle& rc); CTriangle(const CPoint& pt); virtual ~CTriangle(); double GetArea() const; bool ptIn(const CPoint& pt) const; bool InRect(const CRect& rc) const; void Draw() const; void DrawColor(); CShape* Clone() const; CShape& Move(int nOffsetX, int nOffsetY); CPoint m_pts[3]; }; class CRect :virtual public CShape { public: CRect() {} CRect(CPoint pt1, CPoint pt2); CRect(const CRect& rc); CRect(CPoint pt1); virtual ~CRect(); double GetArea() const; bool ptIn(const CPoint& pt) const; bool InRect(const CRect& rc) const; void Draw() const; void DrawColor(); CShape* Clone() const; CShape& Move(int nOffsetX, int nOffsetY); CPoint m_ptLT; CPoint m_ptBR; }; class Comgraphics :public CRect, public CTriangle { public: Comgraphics(const CRect& pt1); Comgraphics(const Comgraphics& rc); Comgraphics(const CPoint pt1); virtual ~Comgraphics(); double GetArea() const; bool ptIn(const CPoint& pt) const; bool InRect(const CRect& rc) const; void Draw() const; void DrawColor(); CShape* Clone() const; CShape& Move(int nOffsetX, int nOffsetY); CPoint m_pt1; CPoint m_pt2; }; #endif
CShape.cpp
#include "CShape.h" #include "graphics.h" #include <iostream> using namespace std; //CShape CShape::CShape() { } CShape::CShape(const CShape& shape) { m_sName = shape.m_sName; } CShape::~CShape() { } double CShape::GetArea() const { return 0; } bool CShape::ptIn(const CPoint& pt) const { return false; } bool CShape::InRect(const CRect& rc) const { return false; } void CShape::Draw() const { } void CShape::DrawColor() { } CShape* CShape::Clone() const { return new CShape(*this); } CShape& CShape::Move(int nOffsetX, int nOffsetY) { return *this; } //CPoint CPoint::CPoint(int nPosX, int nPosY) { m_nPosX = nPosX; m_nPosY = nPosY; } CPoint::CPoint(const CPoint& pt) { m_nPosX = pt.m_nPosX; m_nPosY = pt.m_nPosY; } CPoint::~CPoint() { //cout << "CPoint::~CPoint()\n"; } double CPoint::GetArea() const { return 0; } bool CPoint::ptIn(const CPoint& pt) const { return false; } bool CPoint::InRect(const CRect& rc) const { return rc.ptIn(*this); } void CPoint::Draw() const { circle(m_nPosX, m_nPosY, 2); } void CPoint::DrawColor() { } CPoint* CPoint::Clone() const { return new CPoint(*this); } CPoint& CPoint::Move(int nOffsetX, int nOffsetY) { m_nPosX += nOffsetX; m_nPosY += nOffsetY; return *this; } //CTriangle CTriangle::CTriangle(const CTriangle& tri) { for (int i = 0; i < 3; i++) { m_pts[i] = tri.m_pts[i]; } } CTriangle::~CTriangle() { //cout << "CTriangle::~CTriangle()\n"; } CTriangle::CTriangle(const CPoint& pt1, const CPoint& pt2, const CPoint& pt3) { m_pts[0] = pt1; m_pts[1] = pt2; m_pts[2] = pt3; } CTriangle::CTriangle(const CPoint& pt) { CPoint* pt1 = new CPoint(pt.m_nPosX + 100, pt.m_nPosY + 90); CPoint* pt2 = new CPoint(pt.m_nPosX, pt.m_nPosY + 90); m_pts[0] = pt; m_pts[1] = *pt1; m_pts[2] = *pt2; } CShape& CTriangle::Move(int nOffsetX, int nOffsetY) { for (int i = 0; i < 3; i++) { m_pts[i].Move(nOffsetX, nOffsetY); } return *this; } double CTriangle::GetArea() const { int x1, y1, x2, y2, x3, y3; x1 = m_pts[0].m_nPosX; y1 = m_pts[0].m_nPosY; x2 = m_pts[1].m_nPosX; y2 = m_pts[1].m_nPosY; x3 = m_pts[2].m_nPosX; y3 = m_pts[2].m_nPosY; double bottomLine = sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2)); double verticalLine1 = abs((y1 - y2) * x3 - (x1 - x2) * y3 + (x1 - x2) * y2 - (y1 - y2) * x2); double verticalLine2 = sqrt(pow(y1 - y2, 2) + pow(x1 - x2, 2)); double verticalLine = verticalLine1 / verticalLine2; return (verticalLine * bottomLine) / 2.0; } bool CTriangle::ptIn(const CPoint& pt) const { CTriangle c1 = CTriangle(m_pts[0], m_pts[1], pt); CTriangle c2 = CTriangle(m_pts[1], m_pts[2], pt); CTriangle c3 = CTriangle(m_pts[2], m_pts[0], pt); double totalArea = c1.GetArea() + c2.GetArea() + c3.GetArea(); if (totalArea == this->GetArea()) return true; else return false; } bool CTriangle::InRect(const CRect& rc) const { return rc.ptIn(m_pts[0]) && rc.ptIn(m_pts[1]) && rc.ptIn(m_pts[2]); } void CTriangle::Draw() const { int poly[8] = { m_pts[0].m_nPosX ,m_pts[0].m_nPosY,m_pts[1].m_nPosX,m_pts[1].m_nPosY, m_pts[2].m_nPosX,m_pts[2].m_nPosY, m_pts[0].m_nPosX ,m_pts[0].m_nPosY }; setfillcolor(EGERGB(0xFF, 0xFF, 0xFF)); fillpoly(4, poly); } void CTriangle::DrawColor() { int poly[8] = { m_pts[0].m_nPosX ,m_pts[0].m_nPosY,m_pts[1].m_nPosX,m_pts[1].m_nPosY, m_pts[2].m_nPosX,m_pts[2].m_nPosY, m_pts[0].m_nPosX ,m_pts[0].m_nPosY }; setfillcolor(EGERGB(0xFF, 0xA5, 0x00)); fillpoly(4, poly); } CShape* CTriangle::Clone() const { return new CTriangle(*this); } //CRect CRect::CRect(CPoint pt1, CPoint pt2) { m_ptLT = CPoint(min(pt1.m_nPosX, pt2.m_nPosX), min(pt1.m_nPosY, pt2.m_nPosY)); m_ptBR = CPoint(max(pt1.m_nPosX, pt2.m_nPosX), max(pt1.m_nPosY, pt2.m_nPosY)); } CRect::CRect(const CRect& rc) { m_ptLT = rc.m_ptLT; m_ptBR = rc.m_ptBR; } CRect::CRect(CPoint pt1) { m_ptLT = CPoint(pt1.m_nPosX, pt1.m_nPosY); m_ptBR = CPoint(pt1.m_nPosX + 100, pt1.m_nPosY + 100); } CRect::~CRect() { // cout << "CRect::CRect()\n"; } double CRect::GetArea() const { return (m_ptBR.m_nPosX - m_ptLT.m_nPosX) * (m_ptBR.m_nPosY - m_ptLT.m_nPosY); } bool CRect::ptIn(const CPoint& pt) const { return (pt.m_nPosX >= m_ptLT.m_nPosX && pt.m_nPosX <= m_ptBR.m_nPosX) && (pt.m_nPosY >= m_ptLT.m_nPosY && pt.m_nPosY <= m_ptBR.m_nPosY); } bool CRect::InRect(const CRect& rc) const { return rc.ptIn(m_ptLT) && rc.ptIn(m_ptBR); } void CRect::Draw() const { // Store the x,y coordinates of n vertices int pts[10] = { m_ptLT.m_nPosX,m_ptLT.m_nPosY,m_ptBR.m_nPosX,m_ptLT.m_nPosY, m_ptBR.m_nPosX,m_ptBR.m_nPosY,m_ptLT.m_nPosX,m_ptBR.m_nPosY,m_ptLT.m_nPosX,m_ptLT.m_nPosY }; // To draw a polygon with n vertices, the first parameter must be passed in n+1, pts and the coordinates of the last vertex are the same as the first //drawpoly(5, pts); setfillcolor(EGERGB(0xFF, 0xFF, 0xFF)); fillpoly(5, pts); } void CRect::DrawColor() { int pts[10] = { m_ptLT.m_nPosX,m_ptLT.m_nPosY,m_ptBR.m_nPosX,m_ptLT.m_nPosY, m_ptBR.m_nPosX,m_ptBR.m_nPosY,m_ptLT.m_nPosX,m_ptBR.m_nPosY,m_ptLT.m_nPosX,m_ptLT.m_nPosY }; // To draw a polygon with n vertices, the first parameter must be passed in n+1, pts and the coordinates of the last vertex are the same as the first setfillcolor(EGERGB(0xFF, 0xA5, 0x00)); fillpoly(5, pts); } CShape* CRect::Clone() const { return new CRect(*this); } CShape& CRect::Move(int nOffsetX, int nOffsetY) { m_ptLT.Move(nOffsetX, nOffsetY); m_ptBR.Move(nOffsetX, nOffsetY); return *this; } //Comgraphics Comgraphics::Comgraphics(const CRect&pt1){ m_pt1.m_nPosX = pt1.m_ptBR.m_nPosX; m_pt1.m_nPosY = pt1.m_ptLT.m_nPosY + (pt1.m_ptBR.m_nPosY - pt1.m_ptLT.m_nPosY) / 2; m_pt2.m_nPosX = pt1.m_ptLT.m_nPosX + (pt1.m_ptBR.m_nPosX - pt1.m_ptLT.m_nPosX) / 2; m_pt2.m_nPosY = pt1.m_ptBR.m_nPosY; m_ptLT = pt1.m_ptLT; m_ptBR = pt1.m_ptBR; } Comgraphics::Comgraphics(const Comgraphics& rc){ m_pt1 = rc.m_pt1; m_pt2 = rc.m_pt2; m_ptBR = rc.m_ptBR; m_ptLT = rc.m_ptLT; } Comgraphics::Comgraphics(const CPoint pt1){ m_ptLT = CPoint(pt1.m_nPosX, pt1.m_nPosY); m_ptBR = CPoint(pt1.m_nPosX + 60, pt1.m_nPosY + 80); } Comgraphics::~Comgraphics(){ cout << "Comgraphics::~Comgraphics()" << endl; } double Comgraphics::GetArea() const{ return 0.0; } bool Comgraphics::ptIn(const CPoint& pt) const { return (pt.m_nPosX >= m_ptLT.m_nPosX && pt.m_nPosX <= m_ptBR.m_nPosX) && (pt.m_nPosY >= m_ptLT.m_nPosY && pt.m_nPosY <= m_ptBR.m_nPosY); } bool Comgraphics::InRect(const CRect& rc) const const { return rc.ptIn(m_ptLT) && rc.ptIn(m_ptBR); } void Comgraphics::Draw() const { // Store the x,y coordinates of n vertices int pts[10] = { m_ptLT.m_nPosX,m_ptLT.m_nPosY,m_ptBR.m_nPosX,m_ptLT.m_nPosY, m_ptBR.m_nPosX,m_ptBR.m_nPosY,m_ptLT.m_nPosX,m_ptBR.m_nPosY,m_ptLT.m_nPosX,m_ptLT.m_nPosY }; // To draw a polygon with n vertices, the first parameter must be passed in n+1, pts and the coordinates of the last vertex are the same as the first //drawpoly(5, pts); setfillcolor(GREEN); fillpoly(5, pts); line(m_pt1.m_nPosX, m_pt1.m_nPosY, m_pt2.m_nPosX, m_pt2.m_nPosY); line(m_ptLT.m_nPosX, m_ptLT.m_nPosY, m_pt2.m_nPosX, m_pt2.m_nPosY); line(m_pt1.m_nPosX, m_pt1.m_nPosY, m_ptLT.m_nPosX, m_ptLT.m_nPosY); } void Comgraphics::DrawColor() { // Store the x,y coordinates of n vertices int pts[10] = { m_ptLT.m_nPosX,m_ptLT.m_nPosY,m_ptBR.m_nPosX,m_ptLT.m_nPosY, m_ptBR.m_nPosX,m_ptBR.m_nPosY,m_ptLT.m_nPosX,m_ptBR.m_nPosY,m_ptLT.m_nPosX,m_ptLT.m_nPosY }; // To draw a polygon with n vertices, the first parameter must be passed in n+1, pts and the coordinates of the last vertex are the same as the first setfillcolor(YELLOW); fillpoly(5, pts); line(m_pt1.m_nPosX, m_pt1.m_nPosY, m_pt2.m_nPosX, m_pt2.m_nPosY); line(m_ptLT.m_nPosX, m_ptLT.m_nPosY, m_pt2.m_nPosX, m_pt2.m_nPosY); line(m_pt1.m_nPosX, m_pt1.m_nPosY, m_ptLT.m_nPosX, m_ptLT.m_nPosY); } CShape* Comgraphics::Clone() const { return new Comgraphics(*(this)); } CShape& Comgraphics::Move(int nOffsetX, int nOffsetY) { m_ptLT.Move(nOffsetX, nOffsetY); m_ptBR.Move(nOffsetX, nOffsetY); m_pt1.Move(nOffsetX, nOffsetY); m_pt2.Move(nOffsetX, nOffsetY); return *this; }
3.4.2 operation results