【C语言教程】纯虚函数的实例详解

零 C语言教程评论65字数 4349阅读14分29秒阅读模式

所需工具:

C++

聪明的大脑文章源自灵鲨社区-https://www.0s52.com/bcjc/cyyjc/12487.html

勤劳的双手文章源自灵鲨社区-https://www.0s52.com/bcjc/cyyjc/12487.html

 文章源自灵鲨社区-https://www.0s52.com/bcjc/cyyjc/12487.html

注意:本站只提供教程,不提供任何成品+工具+软件链接,仅限用于学习和研究,禁止商业用途,未经允许禁止转载/分享等文章源自灵鲨社区-https://www.0s52.com/bcjc/cyyjc/12487.html

 文章源自灵鲨社区-https://www.0s52.com/bcjc/cyyjc/12487.html

教程如下

虚函数和纯虚函数

之前学过虚函数,语法:virtual 返回值类型 函数名(参数列表),然后这个类也就变成的虚基类,然后子类重写父类的虚函数。文章源自灵鲨社区-https://www.0s52.com/bcjc/cyyjc/12487.html

纯虚函数,语法:virtual 返回值类型 函数名(参数列表)=0,当类中有了纯虚函数,这个类也称为抽象类。抽象类特点:无法实例化对象,子类必须重写抽象类中的纯虚函数,否则也属于抽象类。文章源自灵鲨社区-https://www.0s52.com/bcjc/cyyjc/12487.html

[php]
class Base
{
public:
virtual void Examp() = 0;//纯虚函数
~Base()
{
cout << "父类的析构函数" << endl;
}
};文章源自灵鲨社区-https://www.0s52.com/bcjc/cyyjc/12487.html

class Son:public Base
{
public:
void Examp()
{
cout << "重写了父类的纯虚函数" << endl;
}文章源自灵鲨社区-https://www.0s52.com/bcjc/cyyjc/12487.html

~Son()
{
cout << "子类的析构函数" << endl;
}
};文章源自灵鲨社区-https://www.0s52.com/bcjc/cyyjc/12487.html

int main()
{
Son p1;
p1.Examp();
system("pause");
}
[/php]

上面是最简单的纯虚函数代码,子类必须得重写重写抽象类中的纯虚函数,不然不能实例化对象。

接下来我们如果利用子类对象开辟堆区,那么会带来父类指针释放子类对象时不干净的问题,即子类的析构函数不能够正常的被调用,会带来内存泄漏的问题:

[php]
int main()
{
Son *p1=new Son;//子类对象开辟堆区
p1->Examp();
delete p1;//释放堆区,自动调用析构函数
system("pause");
}
[/php]

为了解决这个问题,可以利用虚析构和纯虚析构,也很简单,直接在父类的析构函数前面加上virtual关键字就成为了虚析构函数,这个类也会成为抽象类。

[php]
class Base
{
public:
virtual void Examp() = 0;//纯虚函数
virtual ~Base()//虚析构
{
cout << "父类的析构函数" << endl;
}
};
[/php]

或者是利用纯虚析构

[php]
class Base
{
public:
virtual void Examp() = 0;//纯虚函数

virtual ~Base() = 0;//类内声明
};

Base::~Base()//类外实现
{
cout << "父类的析构函数" << endl;
}
[/php]

附:纯虚函数的应用

包含纯虚函数的类叫抽象类,它不能生成对象,用户不能创建类的实例,只能创建派生类的实例。

注明:纯虚函数必须在继承类中重新声明函数(去掉后面的0,否则该派生类也不能实例化)。就是基类告诉子类,“你必须提供一个纯虚函数的实现,但我不知道你会怎样实现它。”

代码实现:

[php]
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;
}
[/php]

总结

虚析构或纯虚析构就是用来解决通过父类指针释放子类对象

如果子类中没有堆区数据,可以不写为虚析构或纯虚析构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

[php]
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));
}
}
[/php]

EnemyPlane

[php]
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 +
'}';
}
}
[/php]

Bullet

[php]
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;
}
}
[/php]

 

 

零
  • 转载请务必保留本文链接:https://www.0s52.com/bcjc/cyyjc/12487.html
    本社区资源仅供用于学习和交流,请勿用于商业用途
    未经允许不得进行转载/复制/分享

发表评论