C++57个入门知识点_47 虚函数的多态性(成员函数中的虚函数具有多态性;构造和析构函数中,虚函数没有多态性;在构造析构函数中调用普通成员函数,该普通成员函数中有虚函数的间接调用,没有多态)

本篇主要讨论两个问题:

1.成员函数中,虚函数是否有多态性?答案为:有;
2.构造和析构函数中,虚函数是否有多态性?答案为:无。

1.成员函数中,虚函数是否有多态性?


成员函数中的虚函数具有多态性。

以下代码中 void test() { foo(); }普通成员函数中,调用的foo();是否具有多态性(间接调用)?

p->test();处设置断点,单步运行

#include <iostream>

class CParent
{
public:

	virtual void foo() {
		printf("void CParent::foo()\r\n");
	}

	//普通成员函数中,调用的foo具有多态性(间接调用,看虚表)
	void test() {
		foo();
	}
};

class CMyclass :public CParent
{
public:
	CMyclass() {}

	virtual ~CMyclass() { }

	virtual void foo() {
		printf("void CMyclass::foo()\r\n");
	}

};

int main(int argc, char* argv[])
{
	//儿子对象的指针赋值给父亲
	CParent* p = new CMyclass;//儿子的内容包含父亲所有内容,指针访问安全

	p->test();

	return 0;
}

运行结果:void test() { foo(); }普通成员函数中,调用的foo()是子类的函数,属于间接调用,具有多态
在这里插入图片描述
因此:普通成员函数中,调用的foo()是具有多态性(间接调用,看虚表)

2.构造和析构函数中,虚函数是否有多态性?


构造和析构函数中,虚函数没有多态性

以下代码中CParent* p = new CMyclass;先会调用子类CParent构造函数,此时父类构造函数中的foo();如果存在多态就会调用子类的函数,但是此时子类的还没有构造好,是无法调用的,因此调用的是父类的foo();函数。

#include <iostream>

class CParent
{
public:
	CParent() {
		foo();
	}
	virtual ~CParent() {

	}
	virtual void foo() {
		printf("void CParent::foo()\r\n");
	}

	void test() {
		foo();
	}
};

class CMyclass :public CParent
{
public:
	CMyclass() {
		foo();
	}
	virtual ~CMyclass() {

	}
	virtual void foo() {
		printf("void CMyclass::foo()\r\n");
	}

};

int main(int argc, char* argv[])
{

	CParent* p = new CMyclass;

	return 0;
}

运行结果:调用父类的函数,不属于间接调用,不具有多态性
在这里插入图片描述
因此在构造函数中调用虚函数,实际上是直接调用,所以没有多态

3.析构函数中调用普通成员函数,该普通成员函数中有虚函数的间接调用


在构造析构函数中调用普通成员函数,该普通成员函数中有虚函数的间接调用,由于进入构造时,会为对象赋值为当前类的虚表,所以没有多态。

如果将上述两种情况结合,构造函数中包含test()函数,test()函数中包含foo();函数,

#include <iostream>

class CParent
{
public:
	CParent() {
		test();
	}
	virtual ~CParent() {

	}
	virtual void foo() {
		printf("void CParent::foo()\r\n");
	}

	void test() {
		foo();
	}
};

class CMyclass :public CParent
{
public:
	CMyclass() {
		foo();
	}
	virtual ~CMyclass() {

	}
	virtual void foo() {
		printf("void CMyclass::foo()\r\n");
	}

};

int main(int argc, char* argv[])
{

	CParent* p = new CMyclass;

	return 0;
}

运行结果: CParent() { test();}中调用父类中的foo();,不存在多态
在这里插入图片描述
在析构函数中调用普通成员函数,该普通成员函数中有虚函数的间接调用,由于进入构造时,会为对象赋值为当前类的虚表,所以没有多态。
在这里插入图片描述
同理当test();是在子类的构造函数中

class CMyclass :public CParent
{
public:
	CMyclass() {
		test();
	}
	virtual ~CMyclass() {

	}
	virtual void foo() {
		printf("void CMyclass::foo()\r\n");
	}

};

运行结果:调用子类的函数
在这里插入图片描述

4.学习视频地址:C++57个入门知识点_47 虚函数的多态性

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十月旧城

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值