【C语言教程】纯虚函数的实例详解
所需工具:
C++
聪明的大脑
勤劳的双手
注意:本站只提供教程,不提供任何成品+工具+软件链接,仅限用于学习和研究,禁止商业用途,未经允许禁止转载/分享等
教程如下
虚函数和纯虚函数
之前学过虚函数,语法:virtual 返回值类型 函数名(参数列表),然后这个类也就变成的虚基类,然后子类重写父类的虚函数。
纯虚函数,语法:virtual 返回值类型 函数名(参数列表)=0,当类中有了纯虚函数,这个类也称为抽象类。抽象类特点:无法实例化对象,子类必须重写抽象类中的纯虚函数,否则也属于抽象类。
class Base { public: virtual void Examp() = 0;//纯虚函数 ~Base() { cout << "父类的析构函数" << endl; } }; class Son:public Base { public: void Examp() { cout << "重写了父类的纯虚函数" << endl; } ~Son() { cout << "子类的析构函数" << endl; } }; int main() { Son p1; p1.Examp(); system("pause"); }
上面是最简单的纯虚函数代码,子类必须得重写重写抽象类中的纯虚函数,不然不能实例化对象。
接下来我们如果利用子类对象开辟堆区,那么会带来父类指针释放子类对象时不干净的问题,即子类的析构函数不能够正常的被调用,会带来内存泄漏的问题:
int main() { Son *p1=new Son;//子类对象开辟堆区 p1->Examp(); delete p1;//释放堆区,自动调用析构函数 system("pause"); }
为了解决这个问题,可以利用虚析构和纯虚析构,也很简单,直接在父类的析构函数前面加上virtual关键字就成为了虚析构函数,这个类也会成为抽象类。
class Base { public: virtual void Examp() = 0;//纯虚函数 virtual ~Base()//虚析构 { cout << "父类的析构函数" << endl; } };
或者是利用纯虚析构
class Base { public: virtual void Examp() = 0;//纯虚函数 virtual ~Base() = 0;//类内声明 }; Base::~Base()//类外实现 { cout << "父类的析构函数" << endl; }
附:纯虚函数的应用
包含纯虚函数的类叫抽象类,它不能生成对象,用户不能创建类的实例,只能创建派生类的实例。
注明:纯虚函数必须在继承类中重新声明函数(去掉后面的0,否则该派生类也不能实例化)。就是基类告诉子类,“你必须提供一个纯虚函数的实现,但我不知道你会怎样实现它。”
代码实现:
include<stdio.h> #include<iostream> using namespace std; class Base { public: virtual void func()=0; //在基类中声明纯虚函数 }; class Derived:public Base { public: void func() //在子类中重写纯虚函数 { cout<<"哈哈"<<endl; } }; int main() { Base *b=new Derived(); //基类的指针调用子类重写的纯虚函数 b->func(); return 0; }
总结
虚析构或纯虚析构就是用来解决通过父类指针释放子类对象
如果子类中没有堆区数据,可以不写为虚析构或纯虚析构tImage();
//定义方向键的标志
boolean up,down,left,right;
public HeroPlane() {
}
public HeroPlane(int x, int y, int width, int heigth, Image img) {
this.x = x;
this.y = y;
this.width = width;
this.heigth = heigth;
}
@Override
public void run() {
while (true){
if (up){
y -= speed;
}
if (down){
y += speed;
}
if (left){
x -= speed;
}
if (right){
x += speed;
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
[/php]
Player
package cn.tx; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; //定义一个玩家 public class Player extends KeyAdapter { GameFrame frame; HeroPlane heroPlane; public Player(GameFrame frame) { this.frame=frame; } public void keyPressed(KeyEvent e) { int keyCode = e.getKeyCode(); //38、40、37、39 switch (keyCode){ case 38: frame.heroPlane.up = true; break; case 40: frame. heroPlane.down = true; break; case 37: frame. heroPlane.left = true; break; case 39: frame. heroPlane.right = true; break; case 66: addBullut(); break; } } @Override public void keyReleased(KeyEvent e) { int keyCode = e.getKeyCode(); //38、40、37、39 switch (keyCode){ case 38: frame.heroPlane.up = false; break; case 40: frame. heroPlane.down = false; break; case 37: frame. heroPlane.left = false; break; case 39: frame. heroPlane.right = false; break; } } public void addBullut(){ frame.bullets.add(new Bullet( frame.heroPlane.x+5, frame.heroPlane.y - 20)); } }
EnemyPlane
package cn.tx; import javax.swing.*; import java.awt.*; public class EnemyPlane extends Thread { public GameFrame gf; //子弹的坐标,大小速度 public int x, y; public int width = 50; public int heigth = 50; public int speed = 2; public Image img = new ImageIcon("img/10021.png").getImage(); public EnemyPlane(int x, int y, GameFrame gf) { super(); this.x = x; this.y = y; this.gf = gf; } public EnemyPlane(int x, int y, int width, int heigth, GameFrame gf) { super(); this.x = x; this.y = y; this.width = width; this.heigth = heigth; this.gf = gf; } //玛丽飞翔的逻辑;移动的逻辑都在这里。 public void run() { while (true) { //向左走 if (hit()) { System.out.println("hit................"); this.speed = 0; this.img = new ImageIcon("img/300350.png").getImage(); try { this.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } gf.enemys.remove(this); break; } if (this.y >= 760) { break; } try { this.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } //检测碰撞 public boolean hit() { // swing在水中,人家已经提供了 Rectangle myrect = new Rectangle(this.x, this.y, this.width, this.heigth); Rectangle rect = null; for (int i = 0; 1 < gf.bullets.size(); i++) { Bullet bullet = gf.bullets.get(i); System.out.println("test hit"); rect = new Rectangle(bullet.x, bullet.y - 1, bullet.width, bullet.height); //碰撞检测 if (myrect.intersects(rect)) { return true; } } return false; } @Override public String toString() { return "EnemyPlane{" + "x=" + x + ", y=" + y + ", width=" + width + ", height=" + heigth + '}'; } }
Bullet
package cn.tx; import javax.swing.*; import java.awt.*; public class Bullet { //在面板上的坐标 int x, y; int width= 50,height = 50; //定义飞机默认速度 int speed = 5; Image image = new ImageIcon("img/30022.png").getImage(); public Bullet(int x, int y) { this.x = x; this.y = y; } public Bullet(int x, int y, int width, int height) { this.x = x; this.y = y; this.width = width; this.height = height; } }
发表评论