IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【C++】虚函数 -> 正文阅读

[C++知识库]【C++】虚函数

虚函数是构成C++多态的重要一步,今天来说一下虚函数!

虚函数:

在基类(或父类)中,使用virtual关键字对函数进行声明为并在一个或多个派生类(子类)中被重新定义的成员函数,通过指向派生类的基类指针或引用,访问派生类中同名覆盖成员函数。

它的用法是这样的virtual + 函数返回类型 + 函数名 +(参数表) {函数体}

首先我们要知道为什么要有虚函数这个东西?

我来看下下面这两段代码的结果再来说结果:

class A
{
public:
	void fun()
	{
		cout << "class A" << endl;
	}
};


class B : public A
{
public:
	void fun()
	{
		cout << "class B" << endl;
	}
};

int main()
{
	A* p = new B;
	p->fun();
	return 0;
}

上述代码很简单,A* p = new B;创建B对象,拿A类型指针指向它,最后运行时,输出的是

?

但是我明明创建的是B对象啊,为什么会运行class A中的fun函数呢?来看下面代码演示:

class A
{
public:
	virtual void fun()
	{
		cout << "class A" << endl;
	}
};


class B :public A
{
public:
	virtual void fun()
	{
		cout << "class B" << endl;
	}
};

int main()
{
	A* p = new B;
	p->fun();
	return 0;
}

和上述代码的唯一区别就是在父类A中和派生类中的fun函数中加了virtual,声明为虚函数

,运行结果是:

?

这个运行结果就达到了我们的预期结果,但是为什么加上virtual声明之后运行结果就不同了呢?

?虚函数的原理:

class A
{
	int num;
public:
	A(int x = 10)
	{

	}
	virtual void fun()
	{
		cout << "class A" << endl;
	}
};


class B :public A
{
	int sum;
public:
	B(int x = 10)
	{

	}
	virtual void fun()
	{
		cout << "class B" << endl;
	}
};

int main()
{
	B b(10);
	A a(50);
	A* p = &b;
	return 0;
}

来看下面的代码分析:

?通过上面我们知道了虚函数的原理,下面我来看一下派生类中成员函数对父类的完全覆盖和部分覆盖的区别:

完全覆盖(基类中所有的虚函数都在子类中被重写)

class A
{
	int num;
public:
	A(int x = 10)
	{

	}
    virtual void fun()
	{
		cout << "class A" << endl;
	}
	virtual void pun()
	{
		cout << "class A::pun" << endl;
	}
};


class B :public A
{
	int sum;
public:
	B(int x = 10)
	{

	}
	virtual void fun()
	{
		cout << "class B" << endl;
	}
    virtual void pun()
	{
		cout << "class B::pun" << endl;
	}

};

int main()
{
    B b(10);
	A* p = &b;
    p->fun();
    p->pun();
	return 0;
}

运行结果:都是调用B中的函数? 没问题,符合我们的预期!

?部分覆盖(基类部分函数在派生类中没有进行重写或者是派生类声明了一些基类中没有的虚函数)

class A
{
	int num;
public:
	A(int x = 10)
	{

	}
	virtual void fun()
	{
		cout << "class A" << endl;
	}
	virtual void pun()
	{
		cout << "class A::pun" << endl;
	}
};


class B :public A
{
	int sum;
public:
	B(int x = 10)
	{

	}
	virtual void fun()
	{
		cout << "class B" << endl;
	}
	virtual void show()    //将class B中的成员函数pun改成show函数
	{
		cout << "class B::pun" << endl;
	}

};

int main()
{
	B b(10);
	A* p = &b;
	p->fun();
	p->pun();
	return 0;
}

首先来看,p指向的函数有两个,fun和pun,但是没有我们刚刚改过的函数show,也就是说,如果在基类中没有的成员函数,但是在继承类中声明为虚函数,也不起作用,不能通过指针来指向。

?运行结果:

?因此想要派生类和基类在函数名相同但是实现不同功能的同时,必须函数名相同,如果在派生类中重写基类中没有的函数,声明为虚函数也没用,不可以通过上述代码中的指针或引用来调用。只可以通过实例化对象来实现对函数的调用(这块虽然show函数声明为虚函数,本质相当于普通成员函数)

总结:

1.父类子类虚函数之间的关系不是重载,而是重写(同名覆盖)。

2.父类指针指向派生类对象的地址,若在有派生类中有基类的重写成员函数,那么父类指针就可以通过虚表去调用派生类的同名覆盖的函数,如若派生类将 基类没有的函数 声明为virtual虚函数,那么就不可以通过基类的指针去之现象该函数,只可以 通过实例化派生类对象去调用这个普通成员函数。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-15 22:13:21  更:2022-03-15 22:16:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:52:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码