c++-多态和vptr指针
多态的原理
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Parent
{
public:
Parent(int a) {
this->a = a;
}
virtual void func(int a)
{
cout << "Parent::func(int)..." << endl;
}
virtual void func(int a, int b, int c)
{
cout << "Parent::func(int ,int ,int )...." << endl;
}
private:
int a;
};
class Child :public Parent
{
public:
Child(int a, int b) :Parent(a)
{
this->b = b;
}
virtual void func(int a)
{
cout << "Child: func(int)..." << endl;
}
void func(int a, int b) {
cout << "Child :func(int ,int )..." << endl;
}
virtual void func(int a, int b, int c)
{
cout << "Child ::func(int ,int ,int )..." << endl;
}
private:
int b;
};
void myFunc(Parent *pp)
{
pp->func(10);
}
int main(void)
{
//Parent *pp = new Parent(10);
//Parent *cp = new Child(100, 200);
Parent *pp = new Child(100, 200);
pp->func(10);//Parent ? Child
//如果调用一个普通函数,编译器根本就不会查找虚函数表。
//只有你调用的函数,是虚函数的时候,才会去查找虚函数表
// myFunc(pp);
pp->func(10, 20, 30);
return 0;
}
验证vptr指针的存在
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Parent
{
public:
virtual void func()
{
cout << "Parent::func().." << endl;
}
virtual void func(int a)
{
cout << "Parent::func().." << endl;
}
private:
int a;
};
class Parent2
{
public:
void func()
{
cout << "Parent2::func().." << endl;
}
private:
int a;
};
int main(void)
{
Parent p1;
Parent2 p2;
cout << "sizeof(p1) " << sizeof(p1) << endl;//多出来的4个字节就是vptr指针所占用的空间。
cout << "sizeof(p2) " << sizeof(p2) << endl;
return 0;
}
vptr指针分布初始化
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Parent
{
public:
Parent(int a)
{
cout << "Parent(int ..)" << endl;
this->a = a;
//print();//是调用父类的print() 还是 子类的print()?
//通过结果 此时调用的父类的print 并不是子类的print
}
virtual void print()
{
cout << "Parent::print()...a = "<<a << endl;
}
private:
int a;
};
class Child :public Parent
{
public:
Child(int a, int b) :Parent(a) //在调用父类的构造器的时候,会将vptr指针当做父类来处理。
//此时会临时指向父类的虚函数表
{
//将子类对象的空间有编程子类对象处理,vptr指针就从指向父类的表 变成 指向子类的表
cout << "Child (int ,int )" << endl;
this->b = b;
print();//此时vptr指针已经回到了 子类的表, 调用的是子类的print函数。
}
virtual void print() {
cout << "Child ::Print()..b = " << b << endl;
}
private:
int b;
};
int main(void)
{
Parent *pp = new Child(10, 20);
// pp->print();//发生多态
delete pp;
return 0;
}
父类指针和子类指针的步长
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Parent
{
public:
Parent(int a)
{
this->a = a;
}
virtual void print()
{
cout << "Parent::print a= " << a << endl;
}
int a;
};
class Child :public Parent
{
public:
Child(int a) :Parent(a)
{
}
virtual void print()
{
cout << "Child::print a= " << a << endl;
}
int b;
};
int main(void)
{
Child array[] = { Child(0), Child(1), Child(2) };
Parent *pp = &array[0];
Child *cp = &array[0];
pp++;
pp->print();
cp->print();
#if 0
pp++;//pp +sizeof(Parent)
cp++;//cp +sizeof(Child)
pp->print();
cp->print();
#endif
cout << "-----" << endl;
int i = 0;
for (cp= &array[0], i = 0; i < 3; i++, cp++) {
cp->print();
}
return 0;
}
c++-多态和vptr指针的更多相关文章
- 深入剖析C++多态、VPTR指针、虚函数表
在讲多态之前,我们先来说说关于多态的一个基石------类型兼容性原则. 一.背景知识 1.类型兼容性原则 类型兼容规则是指在需要基类对象的任何地方,都可以使用公有派生类的对象来替代.通过公有继承,派 ...
- c++多态之——vptr指针
之前做过一个测试,在一个类中定义一个virtual修饰的函数时,sizeof这个类,发现类的大小多了恰好一个指针的字节大小,当初不明白,只是记住有这么一个特性.后来,发现它就是c++编译器给我们添加的 ...
- 这里面盲点很多,构造函数的调用问题,还有vptr指针的++问题(已解决)
#include<iostream> //实现vptr指针初始化问题 using namespace std; class Father { public: Father (int f) ...
- 关于vptr指针初始化的分步
vptr:一个具有虚函数类的对象所具有的隐藏的成员,指向该类的虚函数表. 父类对象的vptr指向是一直指向父类的.但子类的vptr指针最终是指向子类的, 当子类创建的时候,先调用父类构造函数,这个时候 ...
- 53)vptr指针的分布初始化
1)一个父类: 2)一个子类: 3)我的main函数内容 4)通过结果证明 那么产生了问题,这个print是一个虚函数,不应该 在 我的main函数中 通过调用pp->print,在pr ...
- 虚析构函数? vptr? 指针偏移?多态数组? delete 基类指针 内存泄漏?崩溃?
五条基本规则: 1.如果基类已经插入了vptr, 则派生类将继承和重用该vptr.vptr(一般在对象内存模型的顶部)必须随着对象类型的变化而不断地改变它的指向,以保证其值和当前对象的实际类型是一致的 ...
- 关于函数指针与c++多态
原文 https://www.cnblogs.com/zhchngzng/p/4013031.html 虚函数是实现多态的重要元素,请看: class A { public: void a0(){c ...
- c++编译器对多态的实现原理总结
问题:定义一个空的类型,里面没有任何的成员变量或者成员函数,对这个类型进行 sizeof 运算,结果是? 结果是1,因为空类型的实例不包含任何信息,按道理 sizeof 计算之后结果是0,但是在声明任 ...
- C++ 多态的实现原理与内存模型
多态在C++中是一个重要的概念,通过虚函数机制实现了在程序运行时根据调用对象来判断具体调用哪一个函数. 具体来说就是:父类类别的指针(或者引用)指向其子类的实例,然后通过父类的指针(或者引用)调用实际 ...
随机推荐
- K8s 集群节点在线率达到 99.9% 以上,扩容效率提升 50%,我们做了这 3 个深度改造
点击下载<不一样的 双11 技术:阿里巴巴经济体云原生实践> 本文节选自<不一样的 双11 技术:阿里巴巴经济体云原生实践>一书,点击上方图片即可下载! 作者 | 张振(守辰) ...
- Spring Cloud Alibaba基础教程:Nacos服务发现与配置管理
随着微服务概念的流行,越来越多的公司采用`Spring Cloud`全家桶构建微服务系统,实现业务的快速迭代.`Spring Cloud`提供了快速构建分布式微服务常用组件,包括`Spring Clo ...
- 全网最通俗易懂的Kafka入门!
前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 在这篇之前已经写过两篇基础文章了,强烈建议先去阅读: ...
- MySQL Last_SQL_Errno: 1062----经典错误,主键冲突
一.基础信息 1. Centos7.4 2.MySQL 5.7.21 3.基于gtid的复制 二.异常描述 误把从节点当成主节点插入一条数据,同一条数据在主.从节点插入都进行了一次插入操作,导致主键冲 ...
- 1. Python 基础概述 和 环境安装
目录 Python 推荐书籍 开发环境 - Pyenv pyenv 使用 设置Python版本 virtualenv 虚拟环境 pip 通用配置 pip导出和导入 Jupyter 安装和配置 安装 j ...
- Python的特有的参数传递(*和**)
目录 值传递 引用传递 python的传递方式具有两种值传递和引用传递.除此之外,python中还允许包裹方式的参数传递,这未不确定参数个数和参数类型的函数调用提供了基础: 值传递 int.float ...
- SpringBoot源码学习系列之嵌入式Servlet容器
目录 1.博客前言简单介绍 2.定制servlet容器 3.变换servlet容器 4.servlet容器启动原理 SpringBoot源码学习系列之嵌入式Servlet容器启动原理 @ 1.博客前言 ...
- DRF Django REST framework APIView(一)
什么是REST? REST是一个标准,一种规范,遵循REST风格可以使开发的接口通用,便于调用者理解接口的作用. 使url更容易理解,让增删改清晰易懂,在前后端分离开发中按照这一规范能加快开发效率,减 ...
- 实例详解——编译器命令#pragma section作用于函数时作用域是否覆盖到其子函数
在之前的博客[链接脚本(Linker Script)应用实例(一)使用copy table将函数载入到RAM中运行]中,我们第一步使用#pragma section命令将PFlashProgram函数 ...
- idea中自定义快捷键
idea中自定义快捷键 在开发的过程中,总要写一些重复的代码,那么使用自定义快捷键,可以将这些经常用到的代码,自动生成. 1.在idea工具中点击File-->Settings 2.在弹出来的界 ...