c++纯虚函数与虚函数

纯虚函数
  • 纯虚函数形为
virtual void run() = 0;
  • 纯虚函数在基类中是一定没有定义的 只会在基类中声明,并且要求子类一定要重写该函数不然会报错。(类似于java中的接口 ,当具体继承时要求重写所有接口中的方法)
  • 纯虚函数目的是为了实现“运行时多态“,实现同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。
  • "运行时多态"是指一个类函数的调用并不是在编译时刻被确定的,而是在运行时刻被确定的。由于编写代码的时候并不能确定被调用的是基类的函数还是哪个派生类的函数,所以被称为“虚”函数
  • 一个类,只要有纯虚函数就称为抽象类,一个抽象类只能作为基类,而且不能定义抽象类的对象,但是可以定义抽象类的指针,为的是,他可以指向派生类的对象实现多态。
虚函数
  • 虚函数形为
virtual void say() ;
  • 虚函数也是为了实现“运行时多态”
区别
  • 对于虚函数来说,基类可以有定义,子类可以没有定义,也就是可以不重载。
  • 对于纯虚函数来说,基类必须无定义,子类必须有定义,也就是子类中必须重载。
多态例子

下面是一个经典的使用“动态绑定/运行多态”的例子

//头文件
#include<iostream >
using namespace std;
class Animal
{ 
private:
	int height;
public:
	virtual void say()  //虚函数在基类中可以有定义
	{
		cout << "i am animal"<<endl;
	}
	virtual void run() = 0;  //纯虚函数在基类中无定义

 };

class Cat :public Animal
{
private:
	int color;
public:
	void say()  //重写虚函数
	{
		cout << "i am a cat"<<endl;
	}
	void run()  //必须重写纯虚函数
	{
		cout << "cat run" << endl;
	}
};
class Dog :public Animal
{
private:
	int weight;
public:
	void say()
	{
		cout << "i am a dog" <<  endl;
	}
	void run()
	{
		cout << "dog run" << endl;
	}
};
class Person :public Animal
{
private:
	int id;
public:
	void run()  //可以不重载 虚函数 但是必须重载 纯虚函数
	{
		cout << "person run" << endl;
	}
};


//cpp
#include"标头.h"
#include<list>
int main()
{
	//Animal a;
	list<Animal *>animals;

	Animal *a = new Dog();
	Animal *b = new Cat();
	Animal *c = new Person();
	animals.push_back(a);
	animals.push_back(b);
	animals.push_back(c);

	for (auto i : animals)
	{
		i->say();
	}
	for (auto i : animals)
	{
		i->run();
	}




//虚函数
//i am a dog //执行子类方法
//i am a cat //执行子类方法
//i am animal //找不到子类方法后 执行父类方法

//纯虚函数全部执行子类方法
//dog run
//cat run
//person run

	
	return 0;
}


参考资料:
虚函数和纯虚函数的区别
https://blog.youkuaiyun.com/wang13342322203/article/details/80512330
https://blog.youkuaiyun.com/qq_37699336/article/details/78524890

<think>好的,我现在需要详细介绍一下C++中的纯虚函数虚函数。首先,我得回忆一下这两个概念的基本定义和区别。 虚函数(Virtual Function)是在基中使用virtual关键字声明的成员函数,允许在派生中被重写(override)。当通过基指针或引用调用虚函数时,实际调用的是对象的动态型对应的函数版本,这就是多态性的体现。例如,基Animal有一个虚函数speak(),派生Dog和Cat分别重写这个函数,那么通过Animal指针调用speak()会根据实际对象型执行不同的实现。 然后,纯虚函数(Pure Virtual Function)是在基中声明但没有实现的虚函数,通过语法`virtual 返回型 函数名(参数列表) = 0;`来定义。包含纯虚函数称为抽象(Abstract Class),不能实例化,只能作为接口供派生继承。派生必须实现所有的纯虚函数,否则它们也会成为抽象。例如,基Shape有一个纯虚函数draw(),派生Circle和Rectangle必须实现draw()才能被实例化。 接下来,我需要比较两者的区别。虚函数可以有默认实现,而纯虚函数没有,必须由派生实现。含有纯虚函数是抽象,不能创建对象,而含有虚函数仍然可以实例化,除非虚函数被声明为纯虚函数。 还要考虑使用场景。虚函数用于实现运行时多态,允许基提供默认行为,派生可以选择是否覆盖。纯虚函数则用于定义接口,强制派生实现特定方法,确保所有子都有该功能。 可能需要注意的细节包括:构造函数不能是虚函数,而析构函数通常应该是虚函数,尤其是在有继承关系的情况下,以确保正确释放资源。此外,C++11引入了override和final关键字,增强了对虚函数重写的安全性和控制。 需要验证一下纯虚函数是否有例外情况。比如,纯虚函数在基中可以有定义吗?虽然语法上可以提供一个实现,但派生仍然必须重写它,调用时需要明确指定基作用域。这可能在某些设计模式中有用,但比较少见。 最后,总结两者的作用和重要性,强调它们在实现多态和接口设计中的关键角色。可能需要给出简单的代码示例,比如基定义虚函数纯虚函数,派生继承并实现它们,展示多态的行为。</think>以下是C++虚函数纯虚函数的对比详解: 一、核心概念 1. 虚函数(Virtual Function) - 声明方式:基中用 virtual 关键字修饰 - 特性:允许派生重写(override)成员函数 - 调用机制:运行时根据对象实际型动态绑定(动态多态) - 可实例化性:包含虚函数可以实例化 2. 纯虚函数(Pure Virtual Function) - 声明方式:在虚函数声明后加 = 0 - 特性:强制派生必须实现的接口规范 - 特性:使所在成为抽象(不能实例化) - 语法示例:virtual void draw() = 0; 二、核心差异对比表 | 特性 | 虚函数 | 纯虚函数 | |---------------------|-----------------------|--------------------------| | 实现要求 | 基可提供默认实现 | 基无实现,必须由派生实现 | | 实例化能力 | 允许实例化 | 使变为抽象,禁止实例化 | | 派生强制实现要求 | 可选择性重写 | 必须实现所有纯虚函数 | | 典型用途 | 提供可扩展的默认行为 | 定义接口规范 | 三、使用场景分析 1. 虚函数典型应用场景: ```cpp class Animal { public: virtual void speak() { // 可被子覆盖的默认实现 std::cout << "Animal sound" << std::endl; } }; class Dog : public Animal { public: void speak() override { // 选择性覆盖基实现 std::cout << "Woof!" << std::endl; } }; ``` 2. 纯虚函数典型应用场景: ```cpp class Shape { // 抽象基 public: virtual void draw() = 0; // 强制接口规范 }; class Circle : public Shape { public: void draw() override { // 必须实现的接口 std::cout << "Drawing circle" << std::endl; } }; ``` 四、关键注意事项 1. 虚析构函数原则:当存在虚函数时,应声明虚析构函数 ```cpp class Base { public: virtual ~Base() = default; // 虚析构函数确保正确释放资源 }; ``` 2. 现代C++特性(C++11+): - 使用override显式标记重写(提高代码安全性) ```cpp class Derived : public Base { public: void func() override; // 明确表示重写基虚函数 }; ``` 3. 特殊用法:纯虚函数可提供实现(需通过基限定符调用) ```cpp class Interface { public: virtual void api() = 0; }; // 纯虚函数的实现(不常见但合法) void Interface::api() { std::cout << "Default implementation" << std::endl; } class Impl : public Interface { public: void api() override { Interface::api(); // 显式调用基实现 // 添加具体实现... } }; ``` 五、设计模式中的应用 1. 虚函数:模板方法模式(基定义算法框架,子重写具体步骤) 2. 纯虚函数:策略模式(定义统一接口,具体策略强制实现) 理解这两个概念的区别应用场景,是掌握C++面向对象设计和多态编程的关键基础。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值