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++中是一个重要的概念,通过虚函数机制实现了在程序运行时根据调用对象来判断具体调用哪一个函数. 具体来说就是:父类类别的指针(或者引用)指向其子类的实例,然后通过父类的指针(或者引用)调用实际 ...
随机推荐
- 《手把手教你》系列练习篇之2-python+ selenium自动化测试(详细教程)
1. 简介 今天我们还是继续练习练习基本功,各位小伙伴要耐住住性子,要耐得住寂寞啊,不要急躁,后面你会感谢你在前边的不断练习的.到后面也是检验你前边的学习成果的一次很好实践. 本文介绍如何通过link ...
- linux 正确的关机流程
查看系统的使用状态 1.使用who命令查看在线用户. 2.使用netstat -a或ss -tnl查看网络状态: 3.使用ps -aux 查看后台运行的程序. 通过上述操作可以了解系统目前使用状态,从 ...
- linuxRAID(软)
RAID是一种存储机制,英文全名为“RedundantArrays of Inexpensive Disks”,即容错廉价磁盘阵列.RAID可以通过一些技术(硬件或者软件)将多个磁盘整合起来,不仅是一 ...
- Linux -- 进程管理之僵尸进程
UNIX 存在一种机制:在每个进程退出的同时,操作系统释放该进程所有资源,但仍然保留一定的信息(PID / Status / runtime),直到父进程执行 wait() / waitpid(),以 ...
- Java的 FileWriter类 和 FileReader类
一.FileReader类1,构造方法:FileReader fr = new FileReader(String fileName);//使用带有指定文件的String参数的构造方法.创建该输入流对 ...
- salesforce lightning零基础学习(十六) 公用组件之 获取字段label信息
我们做的项目好多都是多语言的项目,针对不同国家需要展示不同的语言的标题.我们在classic中的VF page可谓是得心应手,因为系统中已经封装好了我们可以直接在VF获取label/api name等 ...
- Linux的ftp安装及使用
FTP服务器的安装与配置(Ubuntu)1.查询是否安装vsftpd: rpm -qa |grep vsftpd (rpm的安装:apt-get install rpm) 或者查询当前ftp进程:p ...
- spring cloud 之 -- eureka vs consul,该选择谁?
0--前言 spring cloud的服务注册中心,该选择谁?在选择前,我们首先需要来了解下分布式的CAP定理: 所谓CAP,是指: Consistency:一致性:就是在分布式系统中的所有数据备份, ...
- 2019-2020-1 20199304《Linux内核原理与分析》第三周作业
1.操作系统是如何工作的? 计算机三个法宝(3个关键性的方法机制): 存储程序计算机.函数调用堆栈.中断机制. 1.1堆栈: 在计算机领域,堆栈是一个不容忽视的概念,堆栈是一种数据结构.堆栈都是一种数 ...
- ubuntu16.04 安装cuda9.0+cudnn7.0.5+tensorflow+nvidia-docker配置GPU服务
[摘要] docker很好用,但是在GPU服务器上使用docker却比较复杂,需要一些技巧,下面将介绍一下在ubuntu16.04环境下的GPU-docker环境搭建过程. 第一步: 删除之前的nvi ...