c++ - 抽象类 和 多态当中一些问题

2023-11-19

 抽象类

纯虚函数 

 在虚函数的后面写上 =0 ,则这个函数为纯虚函数。

class A
{
public:
	virtual void func() = 0;
};

纯虚函数不需要写函数的定义,他有类似声明一样的结构。

 抽象类概念

 我们把具有纯虚函数的类,叫做抽象类。

所谓抽象就是,不符合常理的,偶然的,和平常的类不太一样的类。抽象一般是我们人自己想出来的形象,在现实世界当中没有对应的实体,同样的抽象类在现实世界当中没有对应的实体。

 所以,以上描述就引出了抽象类最大的特点:抽象类不能实例化对象

 而且,如果某一个子类的父亲是一个抽象类,那么这个子类也是不能实例化对象的,因为子类继承了父类当中的纯虚函数。那么子类就包含了纯虚函数,主要是包含纯虚函数的类就是抽象类。

 那么,怎样才能让上述的 B 子类能够 实例化对象呢?我们只需要在 B 当中重写一些 A 当中的纯虚函数就可以 让 子类(B类)实例化对象了

// 这是一个抽象类
class A
{
public:
	virtual void func() = 0;
};

// 重写之后就可以 实例化B 对象了
class B : public A
{
public:
	virtual void func()
	{
		cout << "B::func()" << endl;
	}
};

int main()
{
	B b;

	return 0;
}

使用抽象类作为父类,实现出来的子类的多态使用方式,是和普通的一样的。只不过在 父类 当中不在有虚函数表,因为 父类是抽象类,抽象类不能实例化对象,也就不存在虚函数表了。

抽象类当中的多态 和 普通父类的多态在这里多做了一件什么事情呢?

  •  我们知道,父类当中的虚函数,如果子类不进行重写,那么这个虚函数是没有任何作用的;而在抽象类当中,就强制其子类要对抽象类当中的纯虚函数进行重写。
  • 而且这里是 间接性的 强制重写,和之前我们提到的 override 检车重写是不一样的。而且 override 是修饰在派生类当中的,抽象类强制重写,语法是建立在父类当中的。

 多态当中需要注意的点

  •  inline(内联)函数能不能是虚函数?可以,但是,当一个 inline函数 称为虚函数之后,这个函数就不在是inline函数了,因为虚函数需要把地址放到虚表当中,而且内联函数是没有地址的。
  • 静态成员函数不能是 虚函数。如果 把 static 和 virtual 放在一起修饰的话,编译器会直接报错。这是因为,静态成员函数没有 this 指针,静态成员函数是使用 类型::成员函数名 的方式调用的,这样的方式是不能访问到对象当中的虚表的,所以静态成员函数是无法放进虚表的;还有个解释是,静态成员函数是属于类的,不是属于对象的,而只有实例化对象出来之后才能构造处虚表。
  •  构造函数不能是虚函数,如果在构造函数前加 virtual 修饰,就会报错。虚函数表是在编译的时候生成的,而指向虚表的指针是在 构造函数初始化列表的最端初始化的,初始化之后才会指向虚函表, 初始化之前都是随机值。那么,如果构造函数成为了虚函数,而虚函数的作用就是多态,那么在构造函数调用前,虚函数表指针都没有初始化,怎么去找这个构造函数的虚函数呢?所以,构造函数是不能成为虚函数的。
  • 析构函数可以是虚函数。而且,我们最好把父类当中的析构函数定义为虚函数,让子类进行重写。比如这个例子(A是父类,B是子类):A* p = new B;    delete p; 此时,因为 p 指针的类型是 父类A的类型,所以,在调用 detele 的时候,所调用的析构函数就会是 父类 A 的析构函数,那么就会出现问题,但是如果 重写之后,就会调用子类的析构函数。
  • 一个类当中调用普通函数快还是调用虚函数快?如果是普通对象,一样快;如果是指针函数或引用函数,普通函数快。因为此时构成多态。但是,其实两者之间调用时间,差别不大。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c++ - 抽象类 和 多态当中一些问题 的相关文章

  • 检查两个数是否是彼此的排列?

    给定两个数字 a b 使得 1 例如 123 是 312 的有效排列 我也不想对数字中的数字进行排序 如果您指的是数字的字符 例如 1927 和 9721 则 至少 有几种方法 如果允许排序 一种方法是简单地sprintf将它们放入两个缓冲
  • 如何使 Windows 窗体的关闭按钮不关闭窗体但使其不可见?

    该表单有一个 NotifyIcon 对象 当用户单击 关闭 按钮时 我希望表单不关闭而是变得不可见 然后 如果用户想再次查看该表单 可以双击系统托盘中的图标 如果用户想关闭表单 可以右键单击该图标并选择 关闭 有人可以告诉我如何使关闭按钮不
  • C# 和 Javascript SHA256 哈希的代码示例

    我有一个在服务器端运行的 C 算法 它对 Base64 编码的字符串进行哈希处理 byte salt Convert FromBase64String serverSalt Step 1 SHA256Managed sha256 new S
  • 获取按下的按钮的返回值

    我有一个在特定事件中弹出的表单 它从数组中提取按钮并将标签值设置为特定值 因此 如果您要按下或单击此按钮 该函数应返回标签值 我怎样才能做到这一点 我如何知道点击了哪个按钮 此时代码返回 DialogResult 但我想从函数返回 Tag
  • pthread_cond_timedwait() 和 pthread_cond_broadcast() 解释

    因此 我在堆栈溢出和其他资源上进行了大量搜索 但我无法理解有关上述函数的一些内容 具体来说 1 当pthread cond timedwait 因为定时器值用完而返回时 它如何自动重新获取互斥锁 互斥锁可能被锁定在其他地方 例如 在生产者
  • UML类图:抽象方法和属性是这样写的吗?

    当我第一次为一个小型 C 项目创建 uml 类图时 我在属性方面遇到了一些麻烦 最后我只是将属性添加为变量 lt
  • 未解决的包含:“cocos2d.h” - Cocos2dx

    当我在 Eclipse 中导入 cocos2dx android 项目时 我的头文件上收到此警告 Unresolved inclusion cocos2d h 为什么是这样 它实际上困扰着我 该项目可以正确编译并运行 但我希望这种情况消失
  • WPF 中的调度程序和异步等待

    我正在尝试学习 WPF C 中的异步编程 但我陷入了异步编程和使用调度程序的困境 它们是不同的还是在相同的场景中使用 我愿意简短地回答这个问题 以免含糊不清 因为我知道我混淆了 WPF 中的概念和函数 但还不足以在功能上正确使用它 我在这里
  • 如何将图像和 POST 数据上传到 Azure 移动服务 ApiController 终结点?

    我正在尝试上传图片and POST表单数据 尽管理想情况下我希望它是json 到我的端点Azure 移动服务应用 我有ApiController method HttpPost Route api upload databaseId sea
  • 如果使用 SingleOrDefault() 并在数字列表中搜索不在列表中的数字,如何返回 null?

    使用查询正数列表时SingleOrDefault 当在列表中找不到数字时 如何返回 null 或像 1 这样的自定义值 而不是类型的默认值 在本例中为 0 你可以使用 var first theIntegers Cast
  • C# 中的递归自定义配置

    我正在尝试创建一个遵循以下递归结构的自定义配置部分
  • Discord.net 无法在 Linux 上运行

    我正在尝试让在 Linux VPS 上运行的 Discord net 中编码的不和谐机器人 我通过单声道运行 但我不断收到此错误 Unhandled Exception System Exception Connection lost at
  • 如何在 VBA 中声明接受 XlfOper (LPXLOPER) 类型参数的函数?

    我在之前的回答里发现了问题 https stackoverflow com q 19325258 159684一种无需注册即可调用 C xll 中定义的函数的方法 我之前使用 XLW 提供的注册基础结构 并且使用 XlfOper 类型在 V
  • 将 unsigned char * (uint8_t *) 转换为 const char *

    我有一个带有 uint8 t 参数的函数 uint8 t ihex decode uint8 t in size t len uint8 t out uint8 t i hn ln for i 0 i lt len i 2 hn in i
  • C++ fmt 库,仅使用格式说明符格式化单个参数

    使用 C fmt 库 并给定一个裸格式说明符 有没有办法使用它来格式化单个参数 example std string str magic format 2f 1 23 current method template
  • 为什么我收到“找不到编译动态表达式所需的一种或多种类型。”?

    我有一个已更新的项目 NET 3 5 MVC v2 到 NET 4 0 MVC v3 当我尝试使用或设置时编译出现错误 ViewBag Title财产 找不到编译动态表达式所需的一种或多种类型 您是否缺少对 Microsoft CSharp
  • C 中的异或运算符

    在进行按位操作时 我在确定何时使用 XOR 运算符时遇到一些困难 按位与和或非常简单 当您想要屏蔽位时 请使用按位 AND 常见用例是 IP 寻址和子网掩码 当您想要打开位时 请使用包含或 然而 XOR 总是让我明白 我觉得如果在面试中被问
  • 如何在 C++ BOOST 中像图形一样加载 TIFF 图像

    我想要加载一个 tiff 图像 带有带有浮点值的像素的 GEOTIFF 例如 boost C 中的图形 我是 C 的新手 我的目标是使用从源 A 到目标 B 的双向 Dijkstra 来获得更高的性能 Boost GIL load tiif
  • 限制C#中的并行线程数

    我正在编写一个 C 程序来生成并通过 FTP 上传 50 万个文件 我想并行处理4个文件 因为机器有4个核心 文件生成需要更长的时间 是否可以将以下 Powershell 示例转换为 C 或者是否有更好的框架 例如 C 中的 Actor 框
  • 使用按位运算符相乘

    我想知道如何使用按位运算符将一系列二进制位相乘 但是 我有兴趣这样做来查找二进制值的十进制小数值 这是我正在尝试做的一个例子 假设 1010010 我想使用每个单独的位 以便将其计算为 1 2 1 0 2 2 1 2 3 0 2 4 虽然我

随机推荐