【⑦C++ 多态】虚函数 纯虚函数 虚析构 抽象类 多态探究_带你走入虚函数和多态的世界(c+(1)

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新大数据全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注大数据)
img

正文

class Base
{
public:
	Base()
	{
		cout << __FUNCSIG__ << endl;
	}
	virtual ~Base()
	{
		cout << __FUNCSIG__ << endl;
	}
};

class Derive : public Base
{
private:
	char\* _str;
public:
	Derive()
	{
		_str = new char[10] { "kingkiang" };
		cout << __FUNCSIG__ << endl;
	}
	~Derive()
	{
		delete _str;
		cout << __FUNCSIG__ << endl;
	}
};


int main()
{
	Base\* base = new Derive;
	delete base;			
	return 0;
}

5、函数的重载、重写、重定义

A、函数重载
  • 必须在同一个类中进行(作用域相同)
  • 子类无法重载父类的函数,父类同名函数将被名称覆盖
  • 重载是在编译期间根据参数类型和个数决定函数调用
B、函数重定义
  • 发生于父类和子类之间,如果子类写了个和父类函数原型一样的函数,并且父类中的函数没有声明为虚函数,则子类会直接覆盖掉父类的函数
  • 通过父类指针或引用执行子类对象时,会调用父类的函数
C、虚函数重写
  • 必须发生于父类和子类之间
  • 并且父类与子类中的函数必须有完全相同的原型
  • 使用virtual声明之后能够产生多态(如果不使用virtual,那叫重定义)
  • 多态是在运行期间根据具体对象的类型决定函数调用

6、纯虚函数和抽象类

纯虚函数

纯虚函数是一种特殊的虚函数,在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。这就是纯虚函数的作用。

纯虚函数也可以叫抽象函数,一般来说它只有函数名、参数和返回值类型,不需要函数体。这意味着它没有函数的实现,需要让派生类去实现。

C++中的纯虚函数,一般在函数签名后使用=0作为此类函数的标志。Java、C#等语言中,则直接使用abstract作为关键字修饰这个函数签名,表示这是抽象函数(纯虚函数)。

class Animal
{
public:
    virtual void cry() = 0;
}

抽象类

抽象类是对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。

通常在编程语句中用 abstract 修饰的类是抽象类。在C++中,含有纯虚拟函数的类称为抽象类,它不能生成对象;在java中,含有抽象方法的类称为抽象类,同样不能生成对象。

抽象类是不完整的,它只能用作基类。在面向对象方法中,抽象类主要用来进行类型隐藏和充当全局变量的角色。

概念理解

在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。

比如,在一个图形编辑软件的分析设计过程中,就会发现问题领域存在着圆、三角形这样一些具体概念,它们是不同的,但是它们又都属于形状这样一个概念,形状这个概念在问题领域并不是直接存在的,它就是一个抽象概念。而正是因为抽象的概念在问题领域没有对应的具体概念,所以用以表征抽象概念的,抽象类是不能够实例化的。

抽象类特征

  1. 抽象类不能实例化
  2. 抽象类和包含抽象方法(纯虚函数)、非抽象方法和属性
  3. 从抽象类派生的非抽象类,必须对继承过来的所有抽象方法实现
关键字abstract和final

abstract

MSVC独有的关键字,申明类为抽象类

class  Animal abstract
{
};
int main()
{
	Animal a;	//error C3622: “Animal”: 声明为“abstract”的类不能被实例化
	return 0;
}

final

C++标准关键字,结束的意思

  • 禁用虚函数重写
class  Animal 
{
protected:
	virtual void show() final
	{

	}
};

class Dog final :public Animal
{
public:
	void show()override	//error C3248: “Animal::show”: 声明为“final”的函数无法被“Dog::show”重写
	{

	}
};

  • 禁止该类被继承
class  Animal  final
{
};

class Dog final :public Animal //error C3246: "Dog": 无法从 "Animal" 继承,因为它已声明为 "final"
{
};

7、多态探究

多态的理论基础

静态联编和动态联编:联编是指一个程序模块、代码之间互相关联的过程。

  • 静态联编(关联),是程序的匹配、连接在编译阶段实现,也称为早期匹配。
    重载函数使用静态联编。
  • 动态联编(关联),是指程序联编推迟到运行时进行,所以又称为动态联编(迟绑定),将函数体和函数调用关联起来,就叫绑定
    switch 语句和 if 语句是动态联编的例子。

那么C++中的动态联编是如何实现的呢?
如果我们声明了类中的成员函数为虚函数,那么C++编译器会为类生成一个虚函数表,通过这个表即可实现动态联编

多态的本质(原理)

虚函数表是顺序存放虚函数地址的,虚表是顺序表(数组),依次存放着类里面的虚函数。
虚函数表是由编译器自动生成与维护的,相同类的不同对象的虚函数表是一样的。

在这里插入图片描述

既然虚函数表,是一个顺序表,那么它的首地址存放在哪里呢?其实当我们在类中定义了virtual函数时,C++编译器会偷偷的给对象添加一个vptr指针,vptr指针就是存的虚函数表的首地址。

如何证明vptr指针存在

我们可以通过求出类的大小判断是否有vptr的存在

class Dog
{
	void show() {}
};

class Cat
{
	virtual void show() {}
};

int main()
{
	cout << "Dog size:" << sizeof(Dog) << " Cat size:" << sizeof(Cat) << endl;

	return 0;
}


**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注大数据)**
![img](https://img-blog.csdnimg.cn/img_convert/79de9e0d138fc412f04c0f9cc8ba2c69.png)

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

ndl;

	return 0;
}


**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注大数据)**
[外链图片转存中...(img-0JQP9J8D-1713353435971)]

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值