C++实验(二)—— 继承和多态

目录

一、继承访问权限测试

1、概述

2、代码

二、友元类继承测试

1、概述

2、代码

三、多态性综合运用

一般多态性函数

特殊多态性函数

析构函数的多态性

 多继承

设计矢量图(CShape)

CShape.h

CShape.cpp

CShape

CPoint  CTriangle CRect CCircle CircleInRect

ShapeManager

运行结果

 main.cpp

 写代码中遇到的问题 


一、继承访问权限测试

1、概述

C++面向对象的三大特性为:封装、继承、多态

继承是面向对象程序设计中最重要的概念之一。继承的作用是允许我们依据一个类来定义另外一个类,这就意味着创建和维护一个应用程序变得更容易,创建一个类时,不需要再重新编写新的数据成员和函数,而是直接使用已有的类的成员。这个已有的类称为基类,新建的类为派生类。比如,后面代码中的 Animal类是基类,而其他的动物类是派生类。

我们在设计类的时候,可以把属性和行为(成员变量和函数)放在不同的权限下

访问权限有三种:

  • public   公共权限    类内可以访问,类外也可以访问
  • protected   保护权限   类内可以访问,类外不可以访问
  • private   私有权限  类内可以访问,类外不可以访问

其中

  •      private是完全私有的,只有自己可以访问,派生类和外部都不可以访问。
  •      protected是受保护的,只有派生类可以访问,外部不能访问。

同时 

  • 保护继承(protected):如果继承方式为保护继承,基类的公有保护成员将成为派生类的保护成员
  • 私有继承(private):如果继承方式为私有继承,基类的公有保护成员将成为派生类的私有成员

2、代码

  • 设计类A具有public, protected, private等不同属性的成员函数或变量;
  • 类B通过public, protected, private等不同方式继承A,在类B的成员函数中测试访问A的成员函数或变量;
  • 在类B中添加public, protected, private等不同属性的成员函数或变量,在外部测试访问B的各个成员函数或变量;
  • B以private方式继承A,尝试把A中的部分public成员提升为public。
#include<iostream>
using namespace std;

class Person
{
public:
	string name; //姓名
protected:
	string sex;  //性别
private:
	int age;    //年龄
};

//1.public继承
class Student1 :public Person
{
public:
	void test() {
		name = "hello world";
		sex = "male";
		//age=10;  age不可访问
	}
	int weight;//体重
protected:
	int height;//身高
private:
	int eye;//视力

};
//2.protected继承
class Student2 :protected Person
{
public:
	void test() {
		name = "hello world";
		sex = "male";
		//age=10;  age不可访问
	}
	int weight;//体重
protected:
	int height;//身高
private:
	int eye;//视力

};
//3.private继承
class Student3 :private Person
{
public:
	void test() {
		name = "hello world";
		sex = "male";
		//age=10;  age不可访问
	}
	int weight;//体重
protected:
	int height;//身高
private:
	int eye;//视力

};

void test()
{
	Person p;
	p.name;
	p.sex;
	p.age;

	Student1 s1;
	Student2 s2;
	Student3 s3;

	s1.name;
	s1.weight;
	s1.height;
	s1.eye;

	s2.name;
	s2.weight;
	s2.height;
	s2.eye;

	s3.name;
	s3.weight;
	s3.height;
	s3.eye;
}

结果如下图所示

二、友元类继承测试

1、概述

由前面的实验已知,私有成员只能在类的成员函数内部访问,如果想在别处访问对象的私有成员,只能通过类提供的接口(成员函数)间接地进行。

在定义一个类的时候,可以把一些函数(包括全局函数和其他类的成员函数)声明为“友元”,这样那些函数就成为该类的友元函数,在友元函数内部就可以访问该类对象的私有成员了。

2、代码

#include <iostream>

using namespace std;

//设计类A含有私有变量a,在类A中友元给类C;
class A {
private:
	int a;
	friend class C;
};

//设计类B继承A,添加私有变量b;
class B :public A {
private:
	int b;

};

//在类C中测试访问类B的成员变量a, b;
class C {
public:
	void Test() {
		B b1;
		b1.a; //友元 可以成功访问Class A 中的私有变量a
		b1.b;
	}
};

//设计类D继承C,在D的成员函数中测试访问类A的成员变量a,类B的成员变量a, b。
class D :public C {
public:
	void Test() {
		A a1;
		a1.a;
		B b2;
		b2.a;
		b2.b;

	}

};

结果如下图所示

  • 当class A友元给class C 时,则C可访问A中所有成员函数和变量。
  • 友元关系是单向的,不具有交换性。

三、多态性综合运用

一般多态性函数

输入输出参数完全一样,在父类中添加virtual

#include <iostream>

using namespace std;


class Animal{
public:
    void outPut();
};

void Animal::outPut() {
    cout << "Animal output!" << endl;
}

class dog : public Animal {
public:
    void outPut();
};

void dog::outPut() {
    cout << "dog output!" << endl;
}

int main()
{
    Animal p;
    p.outPut();
    dog d;
    d.outPut();
    Animal* ptr = new dog();
    ptr->outPut();
    return 0;
}

子类重写父类的非virtual 方法,当父类指针指向子类对象时,通过指针调用该成员函数,调用的是父类的方法

  

class Animal{
public:
    virtual void outPut();
};

当子类重写父类的virtual函数时。在父类的函数声明中,前面加上virtual,父类指针调用的是实际指向对象的output函数

特殊多态性函数

输入或输出参数 在子类中是父类的指针或基类的引用,在子类中对于的是子类的指针或子类的引用

#include <iostream>

using namespace std;


class Animal{
public:
    virtual void outPut(){
    	cout << "Animal output!" << endl;
	}
	
};

class Dog : public Animal {
public:
    void outPut(){
    	cout << "dog output!" << endl;
	}
};

class Cat : public Animal {
public:
    void outPut(){
    	cout << "cat output!" << endl;
	}
};

	
void out1(Animal & X){ 
	X.outPut();
};

void out2(Animal * X){ 
	X->outPut();
};


int main()
{

	Animal A ;
	out1(A);
	out2(&A);
	
	Dog d;
	out1(d);
	out2(&d);
	
	Cat c;
	out1(c);
	out2(&c); 
	
	return 0;

}

子类可能含有一些父类没有的成员变量或者方法函数,但是子类肯定继承了父类所有的成员变量和方法函数。
所以用父类指针指向子类时,是可以的,因为父类有的,子类都有,不会出现非法访问问题。但是如果用子类指针指向父类的话,一旦访问子类特有的方法函数或者成员变量,就会出现非法。虽然父类指针可以指向子类,但是其访问范围还是仅仅局限于父类本身有的数据,那些子类的数据,父类指针是无法访问的。 

析构函数的多态性

虚析构函数

基类指针可以指向派生类的对象(多态性),如果删除该指针delete []p;就会调用该指针指向的派生类析构函数,而派生类的析构函数又自动调用基类的析构函数,这样整个派生类的对象完全被释放。


#include <iostream>

using namespace std;


class A
{
public:
    virtual ~A(){
		cout<<"A delete"<<endl;
	}
};

class B : public A
{
public:
    ~B(){
	cout<<"B delete"<<endl;
	}
};



int main()
{
    A* a = new B;
    delete a;
    return 0; 
}

运行结果

 多继承

多继承(Multiple Inheritance)是指从多个直接基类中产生派生类的能力,多继承的派生类继承了所有父类的成员

#include <iostream>
using namespace std;

//间接基类A
class A{
protected:
    int m_a;
};

//直接基类B
class B: virtual public A{  //虚继承
protected:
    int m_b;
};

//直接基类C
class C: virtual public A{  //虚继承
protected:
    int m_c;
};

//派生类D
class D: public B, public C{
public:
    void seta(int a){ m_a = a; }  //命名冲突
    void setb(int b){ m_b = b; }  //正确
    void setc(int c){ m_c = c; }  //正确
    void setd(int d){ m_d = d; }  //正确
private:
    int m_d;
};

int main(){
    D d;
    return 0;
} 

因为类 B 和类 C 中都有成员变量 m_a(从 A 类继承而来),编译器不知道选用哪一个,所以产生了歧义

所以,为了解决多继承时的命名冲突和冗余数据问题,C++ 提出了虚继承,使得在派生类中只保留一份间接基类的成员

设计矢量图(CShape)

CShape.h

#pragma once

#ifndef CSHAPE_H
#define CSHAPE_H

#include<QPainter>  https://blog.csdn.net/cpp_learner/article/details/114678143
#include<string>
#include<vector>  
#include<math.h>

using namespace std;

class CPoint;
class CRect;

class CShape {
public:
	CShape();  //构建无参构造器
	CShape(const CShape& shape);
	virtual ~CShape(); //虚析构函数
	virtual double GetArea() const; //获取图形面积 已定义成const的成员函数,一旦企图修改数据成员的值,则编译器按错误处理  https://blog.csdn.net/qq_32739503/article/details/83341222?spm=1001.2101.3001.6661.1&depth_1-
	virtual bool ptIn(const CPoint& pt) const; //判断点是否在图形内 
	
	virtual bool InRect(const CRect& rc) const;
	virtual void Draw(QPainter& painter) const;

	//C++中函数名字前的& 或*   https://blog.csdn.net/weixin_45525272/article/details/106234285
	//https://www.cnblogs.com/fly1988happy/archive/2011/12/14/2286908.html
	virtual CShape* CLone() const;
	virtual CShape& Move(int nOffsetX, int nOffsetY);

	   /* 代码区:存放函数体的二进制代码,由操作系统进行管理的
		全局区:存放全局变量和静态变量以及常量
		栈区:由编译器自动分配释放, 存放函数的参数值, 局部变量等
		堆区:由程序员分配和释放, 若程序员不释放, 程序结束时由操作系统回收*/
protected:
	string m_sName;

};

class CPoint :virtual public CShape
{
public:
	int m_nPosX;
	int m_nPosY;
	CPoint(){}//无参构造器
	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(QPainter & painter) const;
	CPoint * Clone() const;
	CPoint & Move(int nOffsetX, int nOffsetY);
};
class  CTriangle :virtual public CShape
{
public:
	 CTriangle(const CPoint & pt1, const CPoint & pt2, const CPoint & pt3);
     CTriangle(const CTriangle & rc);
     virtual ~CTriangle();
     double GetArea() const;
     bool ptIn(const CPoint & pt) const;
     bool InRect(const CRect & rc) const;
     void Draw(QPainter & painter) const;
     CTriangle * Clone() const;
     CTriangle& 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;
	CShape* Clone() const;
	CShape& Move(int nOffsetX, int nOffsetY);
	CPoint m_ptLT;
	CPoint m_ptBR;
};

class  CCircle : virtual public CShape
{
public:
	 CCircle(CPoint ptCenter, double dR);
     CCircle(const CCircle & rc);
     virtual ~CCircle();
     double GetArea() const;
     bool ptIn(const CPoint & pt) const;
     bool InRect(const CRect & rc) const;
     void Draw(QPainter & painter) const;
     CCircle * Clone() const;
     CCircle & Move(int nOffsetX, int nOffsetY);

	 CPoint m_ptCenter;
     double m_dR;
 };

class  CircleInRect : public CCircle, public CRect
{
 public:
	 CircleInRect(CPoint ptCenter, double dR);
     CircleInRect(const CircleInRect & rc);
     virtual ~CircleInRect();
     double GetArea() const;
     bool ptIn(const CPoint & pt) const;
     bool InRect(const CRect & rc) const;
     void Draw(QPainter & painter) const;
     CircleInRect * Clone() const;
     CircleInRect & Move(int nOffsetX, int nOffsetY);
 };

class ShapeManager
{
public:
	ShapeManager();
	void Add(CShape* pShape); //增加图形
	void Remove(CShape* pShape);//删除图形
	void Add(vector<CShape*> shapes);
	void Remove(vector<CShape*> shapes);
	void RemoveAll();
	~ShapeManager();


	//注意看
     CShape * ptIn(const CPoint & pt);//get the first selected
     bool InRect(const CRect & rc, vector<CShape*> &shapesOut);
     void Draw(QPainter & painter, vector<CShape*>&shapes);
     void Draw(QPainter & painter);
     //auto input m_pShapes after cloned
	void Clone(vector<CShape*>&shapesIn, vector<CShape*>&shapesOut);
     void Move(int nOffsetX, int nOffsetY, vector<CShape*> &shapes);

 private:
	vector<CShape*> m_pShapes;
	
};
};
#endif // !CSHAPE_H

CShape.cpp

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(QPainter & painter) const
{
}
CShape* CShape::CLone() const
{
    return new CShape(*this);
}
CShape& CShape::Move(int nOffsetX, int nOffsetY)
{
    return *this;
}

CPoint  CTriangle CRect CCircle CircleInRect

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(QPainter& painter) const
{
    painter.drawPoint(m_nPosX, m_nPosY);
}
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(const CPoint& pt1, const CPoint& pt2, const CPoint& pt3) {
    m_pts[0] = pt1;
    m_pts[1] = pt2;
    m_pts[2] = pt3;
}

//移动三角形
CTriangle& CTriangle::Move(int nOffsetX, int nOffsetY) {
    for (int i = 0; i < 3; i++) {
        m_pts[i].Move(nOffsetX, nOffsetY);
    }
    return *this;
}

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";
}
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(QPainter & painter) const
 {
     painter.drawLine(m_pts[0].m_nPosX, m_pts[0].m_nPosY, m_pts[1].m_nPosX, m_pts[1].m_nPosY);
     painter.drawLine(m_pts[1].m_nPosX, m_pts[1].m_nPosY, m_pts[2].m_nPosX, m_pts[2].m_nPosY);
     painter.drawLine(m_pts[2].m_nPosX, m_pts[2].m_nPosY, m_pts[0].m_nPosX, m_pts[0].m_nPosY);
}

//矩形
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()
{
     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(QPainter &painter) const
{
    painter.drawRect(m_ptLT.m_nPosX,m_ptLT.m_nPosY)
}

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);
// https://www.html.cn/softprog/c/11422084099400.html
	return *this;
}


CCircle::CCircle(CPoint ptCenter,double dR)
{
   m_ptCenter = ptCenter;
    m_dR = dR;
}
CCircle::CCircle(const CCircle & rc)
{
    m_ptCenter = rc.m_ptCenter;
     m_dR = rc.m_dR;
}
CCircle::~CCircle()
{
    cout<<"Circle"<<endl;
}

double CCircle::GetArea() const
{
    return m_dR*m_dR;
}
bool CCircle::ptIn(const CPoint& pt) const
{
    return  (pt.m_nPosX - m_ptCenter.m_nPosX)*(pt.m_nPosX - m_ptCenter.m_nPosX)+(pt.m_nPosY- m_ptCenter.m_nPosY)*(pt.m_nPosY- m_ptCenter.m_nPosY)<m_dR*m_dR;   
}
bool CCircle::InRect(const CRect& rc) const
{
    return ((m_ptCenter.m_nPosX - m_dR)>rc.m_ptLT.m_nPosX)&&
            ((m_ptCenter.m_nPosY - m_dR)>rc.m_ptLT.m_nPosY)&&
            ((m_ptCenter.m_nPosX+m_dR)<rc.m_ptBR.m_nPosX)&&
             ((m_ptCenter.m_nPosY+m_dR)<rc.m_ptBR.m_nPosY);
}
void CCircle::Draw(QPainter & painter) const
{
     painter.drawEllipse(m_ptCenter.m_nPosX,m_ptCenter.m_nPosY,m_dR,m_dR);
 }
CCircle* CCircle::Clone() const
{
    return new CCircle(*this);
}
CCircle& CCircle::Move(int nOffsetX,int nOffsetY)
{
    m_ptCenter.m_nPosX+=nOffsetX;
    m_ptCenter.m_nPosY+=nOffsetY;
    return  *this;
}

CircleInRect::CircleInRect(CPoint ptCenter,double dR):
    CCircle(ptCenter,dR),CRect(CPoint(ptCenter.m_nPosX - m_dR,ptCenter.m_nPosY - m_dR),CPoint(ptCenter.m_nPosX + m_dR,ptCenter.m_nPosY + m_dR))
{

}
CircleInRect::CircleInRect(const CircleInRect & rc):
    CCircle(rc.m_ptCenter,rc.m_dR),CRect(rc.m_ptLT,rc.m_ptBR)
{

}
CircleInRect::~CircleInRect()
{

}

ShapeManager

//ShapeManager
ShapeManager::ShapeManager()
{

}
void ShapeManager::Add(CShape *pShape)
{
    m_pShapes.push_back(pShape);
}
void ShapeManager::Remove(CShape *pShape)
{
    for(vector<CShape*>::iterator it=m_pShapes.begin();it!=m_pShapes.end();it++){
        if(*it==pShape)
        {
            delete pShape;
            m_pShapes.erase(it);
        }
    }
}
void ShapeManager::Add(vector<CShape*> shapes)
{
    m_pShapes.insert(m_pShapes.begin(),shapes.begin(),shapes.end());

}
void ShapeManager::Remove(vector<CShape*> shapes)
{
     for (vector<CShape*>::iterator it = m_pShapes.begin();it!=m_pShapes.end();it++) {
        Remove(*it);
    }
}
void ShapeManager::RemoveAll()
{
    for (vector<CShape*>::iterator it = m_pShapes.begin();it!=m_pShapes.end();it++) {
        delete *it;
   }
    m_pShapes.clear();
}

ShapeManager::~ShapeManager()
{
    RemoveAll();
}

CShape * ShapeManager::ptIn(const CPoint& pt)
{
     for (vector<CShape*>::iterator it = m_pShapes.begin();it!=m_pShapes.end();it++) {
        if((*it)->ptIn(pt))
        {
            return *it;
        }
    }
    return  NULL;
}

bool ShapeManager::InRect(const CRect& rc,vector<CShape*> &shapesOut)
{
    shapesOut.clear();
     for (vector<CShape*>::iterator it = m_pShapes.begin();it!=m_pShapes.end();it++) {
        if((*it)->InRect(rc))
        {
            shapesOut.push_back(*it);
         }
    }
}

void ShapeManager::Draw(QPainter& painter, vector<CShape*>& shapes)
{
   for (vector<CShape*>::iterator it = shapes.begin();it!=shapes.end();it++) {
        (*it)->Draw(painter);
    }
}

void ShapeManager::Draw(QPainter& painter)
{
    for (vector<CShape*>::iterator it = m_pShapes.begin();it!=m_pShapes.end();it++) {
        (*it)->Draw(painter);
    }
}

void ShapeManager::Clone(vector<CShape*>& shapesIn,vector<CShape*>& shapesOut)
{
    shapesOut.clear();
    for (vector<CShape*>::iterator it = shapesIn.begin();it!=shapesIn.end();it++) {
        shapesOut.push_back((*it)->CLone());
   }
}

void ShapeManager::Move(int nOffsetX, int nOffsetY, vector<CShape *> &shapes)
{
    for(vector<CShape*>::iterator it=shapes.begin();it!=shapes.end();it++)
    {
        (*it)->Move(nOffsetX,nOffsetY);
    }
}

运行结果

 

 main.cpp

void MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    //需要画图的内容
    //设置画笔颜色
    painter.setPen(QPen(QColor(0, 160, 230), 10));
    
    

    //设置点
    CPoint *point1=new CPoint(300,200);
    CPoint *point2=new CPoint(150,260);
    CPoint *point3=new CPoint(200,140);

    //point1->Draw(painter);
    //point2->Draw(painter);
    //point3->Draw(painter);

     //画三角形
    CTriangle *triangle;
    triangle=new CTriangle(*point1,*point2,*point3);
    //triangle->Draw(painter);


    //矩形
    CRect *rect=new CRect(*point1,*point2);
    //rect->Draw(painter);
    //圆形
    CPoint *center=new CPoint(300,300);
    CCircle *circle=new CCircle(*center,50);
    //circle->Draw(painter);

    CPoint *point4=new CPoint(300,140);

    printf("getarea %f\n",triangle->GetArea());
    printf("ptIn %d\n",triangle->ptIn(*point4));

    triangle->Move(100,100);
    triangle->Draw(painter);


    //ShapeManager测试
    double r=50.0;

    ShapeManager *shapemanager=new ShapeManager();
    vector<CShape *> shapes;

    for (vector<CPoint *>::iterator it=points.begin();it!=points.end();it++)
    {
        CShape *test = new CCircle(**it,r);
        shapes.push_back(test);
    }


    CShape *shape =new CTriangle(*point1,*point2,*point3);

    shapemanager->Add(shape);
    shapemanager->Add(shapes);

    shapemanager->Draw(painter);

 写代码中遇到的问题 

C++函数的返回值 : 返回引用类型和非引用类型

引用类型:在函数的参数中,包含有以引用方式或指针方式存在的,需要被返回的参数。

非引用类型:函数的返回值用于初始化在调用函数时创建的临时对象(temporary object),如果返回类型不是引用,在调用函数的地方会将函数返回值复制给临时对象

int& abc(int a, int b, int c, int& result)

{
     result = a + b + c;
     return result;
}

C++函数的返回值——返回引用类型&非引用类型https://www.cnblogs.com/fly1988happy/archive/2011/12/14/2286908.html

vector

C++ vector使用方法_w3cschoolhttps://www.w3cschool.cn/cpp/cpp-i6da2pq0.html

QT Painter

 要想在绘图设备上(一般是窗口部件)上绘图,只需创建一个QPainter,再将指针传到该设备中

        (10条消息) QT使用QPainter绘图_hao_zong_yin的博客-CSDN博客https://blog.csdn.net/hao_zong_yin/article/details/73252571?spm=1001.2101.3001.4242.3

猜你喜欢

转载自blog.csdn.net/m0_50945459/article/details/120886142
今日推荐