在父类的构造函数中调用虚函数为什么不能实现多态

简介: 在父类的构造函数中调用虚函数为什么不能实现多态

问题描述

大家都知道在面向对象语言中,多态实际上就是接口的多种不同的实现方式,而虚函数实现多态的机制就是通过指向派生类的基类指针或引用,访问派生类中同名覆盖的成员函数。那么有人知道为什么在父类的构造函数中调用了虚函数却不能实现多态吗?

问题分析

在最初接触到这个问题的时候,也很茫然,好像都知道不能在父类的构造函数里通过调用虚函数来实现多态,但是至于为什么还真的没有想过。但是遇到了这个问题不能不解决呀,所以又要开始发扬打破砂锅问到底的“好品质”了。

首先在查看虚函数实现多态的方法描述里就能知道,虚函数之所以能实现多态完全得益于vptr指针和虚函数表,那么vptr指针到底是什么?虚函数表又是什么?他们之间又有什么关系呢?

解决方案

vptr指针:当类中声明虚函数时,编译器就会在类中自动生成一个虚函数表,同时编译器会在类实例化对象时在对象中加入vptr指针,且指向这个虚函数表。

虚函数表:其实虚函数就是是通过一张虚函数表来实现的,简称为V-Table。在这个表中,主要是一个类的虚函数的地址,这张表解决了继承、覆盖的问题,保证其真实反应实际的函数。这样,当用父类的指针来操作一个子类的时候,这张虚函数表就显得尤为重要了,它就像一个地图一样,指明了实际所应该调用的函数。

因为vptr指针变量是在构造函数中进行初始化的,且初始化过程为:首先对象在创建的时,由编译器对VPTR指针进行初始化 ,只有当对象的构造完全结束后VPTR的指向才最终确定。

所以当构造函数被调用时,编译器生成的VPTR指针只能产生通向它自己的虚函数表的调用,而不是指向最后派生的虚函数表,因为所有构造函数只有被调用后才会有最后派生的虚函数表,且不能知道有哪些子类继承自该父类。

所以这就是为什么在父类构造函数中调用虚函数不能实现多态的原因。

目录
相关文章
|
8月前
|
C#
C# 继承类中(父类与子类)构造函数的调用顺序
C# 继承类中(父类与子类)构造函数的调用顺序
|
9月前
|
编译器 C++
C++的基类和派生类构造函数
基类的成员函数可以被继承,可以通过派生类的对象访问,但这仅仅指的是普通的成员函数,类的构造函数不能被继承。构造函数不能被继承是有道理的,因为即使继承了,它的名字和派生类的名字也不一样,不能成为派生类的构造函数,当然更不能成为普通的成员函数。 在设计派生类时,对继承过来的成员变量的初始化工作也要由派生类的构造函数完成,但是大部分基类都有 private 属性的成员变量,它们在派生类中无法访问,更不能使用派生类的构造函数来初始化。 这种矛盾在C++继承中是普遍存在的,解决这个问题的思路是:在派生类的构造函数中调用基类的构造函数。 下面的例子展示了如何在派生类的构造函数中调用基类的构造函数:
49 0
|
8月前
|
编译器 C++
C++中虚继承时的构造函数
在虚继承中,虚基类是由最终的派生类初始化的,换句话说,最终派生类的构造函数必须要调用虚基类的构造函数。对最终的派生类来说,虚基类是间接基类,而不是直接基类。这跟普通继承不同,在普通继承中,派生类构造函数中只能调用直接基类的构造函数,不能调用间接基类的。 下面我们以菱形继承为例来演示构造函数的调用: #include <iostream> using namespace std; //虚基类A class A{ public: A(int a); protected: int m_a; }; A:
56 1
|
10月前
|
程序员
为什么子类会调用父类无参的构造函数
为什么子类会调用父类无参的构造函数
|
10月前
|
C++
<c++> 类的继承 | 基类与派生类 | 构造函数与析构函数
<c++> 类的继承 | 基类与派生类 | 构造函数与析构函数
97 0
|
11月前
|
编译器 C语言 C++
C++ 继承,构造函数,析构函数(上)
C++ 继承,构造函数,析构函数
|
11月前
|
C++
C++ 继承,构造函数,析构函数(下)
C++ 继承,构造函数,析构函数
|
11月前
|
C++
【为什么】构造函数中可以调用虚函数吗?
【为什么】构造函数中可以调用虚函数吗?
|
12月前
|
C++
基类派生类多态虚函数?
通常在层次关系的根部有一个基类,其他类则直接或间接的从基类继承而来,这些继承得到的类称为派生类。基类负责定义在层次关系中所有类共同拥有的成员,而每个派生类定义各自特有的成员。
93 0
|
存储 设计模式 安全
如何理解子类对象赋值给父类(深入理解动态绑定、静态绑定)
如何理解子类对象赋值给父类(深入理解动态绑定、静态绑定)
如何理解子类对象赋值给父类(深入理解动态绑定、静态绑定)