C++ -- 虚函数和纯虚函数

本文详细解释了虚函数和纯虚函数的概念、用法及在多态中的应用,包括如何通过基类指针调用子类同名函数、抽象类的特性以及虚函数在多态中的使用方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、定义

都有virtual关键字

一个函数为虚函数,该函数可以实现,允许用基类的指针调用子类的同名函数。

一个函数为纯虚函数,该函数不能实现,子类继承这个类必须实现这个函数才能实例化对象。

class A
{
public:
	virtual void func();//虚函数
}
class B
{
public:   
	virtual void func()=0;//纯虚函数
};

void main()
{
	A a;
	B b; // 不允许,因为类B中有纯虚函数,不能实例化对象
	system("pause");
}

2、用法

有纯虚函数的类是抽象类,不能生成对象,只能派生。

他派生的类的纯虚函数没有被改写,那么,它的派生类还是个抽象类。

定义纯虚函数就是为了让基类不可实例化。

虚函数在多态中间的使用: 多态一般就是通过基类的指针在运行时刻调用子类来实现的。

1)有virtual关键字

//定义基类animal,有虚函数born()
class animal 
{ 
public:  
    void fun1(animal *dog_cat); 
    virtual void born(); 
}; 

void animal::fun1(animal *dog_cat) 
{ 
    dog_cat->born(); 
} 
void animal::born() 
{ 
    cout<< "This is animal."<<endl; 
} 
//定义animal的子类dog
class dog: public animal 
{ 
public: 
    virtual void born(); 
}; 
void dog::born()
{ 
    cout<<"This is dog."<<endl; 
} 
//定义animal的子类cat
class cat:public animal 
{ 
public: 
    virtual void born(); 
}; 
void cat::born()
{ 
    cout<<"This is cat."<<endl; 
} 

void main() 
{ 
    animal a; 
    dog b; 
    cat c;     
    a.fun1(&c);
    a.fun1(&b);
    system("pause");  
}  

输出结果:

2)没有virtual关键字

//定义基类animal,无虚函数
class animal 
{ 
public:  
    void fun1(animal *dog_cat); 
    void born(); 
}; 

void animal::fun1(animal *dog_cat) 
{ 
    dog_cat->born(); 
} 

void animal::born() 
{ 
    cout<< "This is animal."<<endl; 
} 
//定义animal的子类dog
class dog: public animal 
{ 
public: 
    void born(); 
}; 
void dog::born()
{ 
    cout<<"This is dog."<<endl; 
} 
//定义animal的子类cat
class cat:public animal 
{ 
public: 
    void born(); 
}; 
void cat::born()
{ 
    cout<<"This is cat."<<endl; 
} 

void main() 
{ 
    animal a; 
    dog b; 
    cat c;     
    a.fun1(&c);
    a.fun1(&b);
    system("pause");  
}  

输出结果:

只要基类的成员函数是虚函数,派生类的同名函数(参数相同,返回值类型相同),函数体不同,不管有没有显式声明virtual都是虚函数。

派生类中virtual关键字可有可无,但是也是虚函数。

#include "stdafx.h"
#include "iostream"
using namespace std;

class A
{
	int x;
public:
	A(int i) {x=i;}
	void show()
	{
		cout<<"A class show():x="<<x<<endl;
	}
	virtual void display()
	{
		cout<<"A class virtual display():x="<<x<<endl;
	}
};

class B:public A
{
	int y;
public:
	B(int i,int j):A(i) { y=j;}
	void show()
	{
		cout<<"B class show(): y="<<y<<endl;
	}
	void display()//前面有无virtual都可以
	{
		cout<<"B class virtual display():y="<<y<<endl;
	}

};
int main(int argc, _TCHAR* argv[])
{
	A a(5),*pa;
	B b(10,20);
	pa=&b;
	pa->show();
	pa->display();
	system("pause");
	return 0;
}

A class show():x=10

B class virtual display():y=20

基类的指针指向派生类的对象,当调用同名的成员函数时:

1)如果在基类中成员函数为虚函数,那么基类指针调用的就是派生类的同名函数。

virtual void display();

可以这么理解:因为该函数是虚的,所以会找真正实现的那个函数,所以调用派生类B中的 B class virtual display.

2)如果基类中成员函数为非虚函数,则调用的是基类的成员函数。

void show();  因为基类是非虚的,已经完全实现了,所以没有必要再调用派生类的了,就调用基类的A class show()。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值