【C++】多态 ⑨ ( vptr 指针初始化问题 | 构造函数 中 调用 虚函数 - 没有多态效果 )
  K1I6GvxBEuyy 2023年12月02日 35 0



文章目录

  • 一、vptr 指针初始化问题
  • 1、vptr 指针与虚函数表
  • 2、vptr 指针初始化时机
  • 3、构造函数 中 调用 虚函数 - 没有多态效果
  • 4、代码示例




构造函数 的 作用就是 创建对象 , 构造函数 最后 一行代码 执行完成 , 才意味着 对象构建完成 , 对象构建完成后 , 才会将 vptr 指针 指向 虚函数表 ;

如果在 构造函数 中 调用 虚函数 , 则 没有 多态效果 ;






一、vptr 指针初始化问题




1、vptr 指针与虚函数表



" 虚函数表 " 由 C++ 编译器 负责 创建 与 维护 , 被 virtual 关键字 修饰的 虚函数 , 会自动 被 C++ 编译器 存储到 " 虚函数表 " 中 , 类中会自动添加一个 " vptr 指针 " 成员变量 指向 虚函数表 ;



2、vptr 指针初始化时机



对象中的 vptr 指针 指向 虚函数表 ,

在 对象 被 创建时 , 由 C++ 编译器 对 对象中的 vptr 指针进行初始化操作 ,

对象 创建完成 后 , 也就是 虚函数 整理完毕 , 全部放到 虚函数表 中后 ,

vptr 指针 才会指向 虚函数表 的首地址 ;



父类 对象 的 vptr 指针 指向 父类 的 虚函数表 首地址 ;

子类 对象 的 vptr 指针 指向 子类 的 虚函数表 首地址 ;



3、构造函数 中 调用 虚函数 - 没有多态效果



构造函数 的 作用就是 创建对象 ,

构造函数 最后 一行代码 执行完成 , 才意味着 对象构建完成 ,

对象构建完成后 , 才会将 vptr 指针 指向 虚函数表 ;



如果在 构造函数 中 调用 虚函数 , 则 没有 多态效果 ;

在 父类 的 构造函数中 , 调用了 父类的 虚函数 ;

此时 , 如果 创建 子类对象 , 执行 父类构造函数 , 仍然调用 父类 的虚函数 , 子类的虚函数 没有被调用 , 说明 构造函数 执行期间 , 多态没有生效 ;



参考 【C++】继承 ⑧ ( 继承 + 组合 模式的类对象 构造函数 和 析构函数 调用规则 ) 博客中的 构造函数 调用规则 :

  • 构造函数 : 父类 -> 成员 -> 自身 ;
  • 首先 , 调用 父类 构造函数 ;
  • 然后 , 调用 成员 构造函数 ; 也就是 成员变量 类型的 构造函数 ;
  • 最后 , 调用 自己 构造函数 ; 自身定义的 构造函数 ;
  • 析构函数 : 自身 -> 成员 -> 父类 ;
  • 首先 , 调用 自己 析构函数 ; 自身定义的 析构函数 ;
  • 然后 , 调用 成员 析构函数 ; 也就是 成员变量 类型的 析构函数 ;
  • 最后 , 调用 父类 析构函数 ;


4、代码示例



执行 Child c; 代码 , 创建 子类对象 ;

构造函数调用顺序是 父类 -> 成员 -> 自身 ;

首先 , 调用 父类 的 构造函数 , 然后再 父类构造函数 中调用 fun 虚函数 , 只能调用 父类本身的 fun 函数 , 此时 vptr 指针没有指向 虚函数表 , 虚函数表未生效 , 只能调用 父类的 fun 函数本身 ;

  • 父类的 构造函数 调用完毕后 , vptr 指针 才指向 父类的 虚函数表 ;

然后 , 调用 子类 的构造函数 , 此时在 子类构造函数 中调用 fun 虚函数 , 只能调用 子类本身的 fun 函数 , 此时 vptr 指针没有指向 虚函数表 , 虚函数表未生效 , 只能调用 子类的 fun 函数本身 ;

  • 子类的 构造函数 调用完毕后 , vptr 指针 才指向 子类的 虚函数表 ;


代码示例 :

#include "iostream"
using namespace std;

// 父类
class Parent {
public:
	Parent()
	{
		cout << "调用父类构造函数" << endl;

		// 构造函数中调用父类的虚函数
		// 如果创建子类 , 此处调用的仍是 父类的 虚函数
		fun(1);
	}

	virtual void fun(int a)
	{
		cout << "执行 父类 Parent 的 virtual void fun(int a) 函数" << endl;
	}
};

class Child : public Parent
{
public:
	Child()
	{
		cout << "调用子类构造函数" << endl;
		// 构造函数中调用子类的虚函数
		// 如果创建子类 , 此处调用的仍是 子类的 虚函数 
		// 多态未生效
		fun(1);
	}

	virtual void fun(int a)
	{
		cout << "执行 子类 Child 的 virtual void fun(int a) 函数" << endl;
	}
};


int main() {

	Child c;
	
	// 控制台暂停 , 按任意键继续向后执行
	system("pause");

	return 0;
}

执行结果 :

调用父类构造函数
执行 父类 Parent 的 virtual void fun(int a) 函数
调用子类构造函数
执行 子类 Child 的 virtual void fun(int a) 函数
请按任意键继续. . .

【C++】多态 ⑨ ( vptr 指针初始化问题 | 构造函数 中 调用 虚函数 - 没有多态效果 )_多态


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月02日 0

暂无评论

推荐阅读
K1I6GvxBEuyy
作者其他文章 更多