(1).对象类型:
          a.静态类型:对象声明时的类型,编译的时候确定
          b.动态类型:对象的类型是运行时才能确定的
class A
{};
class B:public A
{};
int main()
{
B* b;
A* a=b;//a的静态类型是A*,动态类型(运行时)类型是B*
return ;
}
(2).多态
          a.静态多态:函数重载、泛性编程   
int Add(int a,int b)
{
return a+b;
}
float Add(float a,float b)
{
return a+b;
}
int main()
{
cout<<Add(,)<<endl;;
cout<<Add(10.1f,20.2f)<<endl;;
return ;
}
在编译期间,编译器会根据函数实参的类型推断要调用那个函数
b.动态多态:虚函数
               1>.每个类都维护这一张虚表;调用虚函数查看对象是那个类,然后查表
               2>.基类可以使用为纯虚函数(virtual void fun()=0),基类就是抽象类要求子类实现

虚函数:
               含有虚函数或其父类含有虚函数的类,编译器都会为其添加一个虚函数表,vptr,
               虚基类表:虚继承产生虚基类表(vbptr),虚基表的内容与虚基表完全不同
               
**1**、单继承
           1)子类重写父类虚函数:
class A
{
public:
virtual void fun()
{
cout<<"A-fun()"<<endl;
}
A()
{}
~A()
{}
private:
int a1;
};
class B:public A
{
public:
void fun()
{
cout<<"B-fun()"<<endl;
}
B()
{}
~B()
{}
private:
int b1;
};
 

2)子类定义了新的虚函数:

class A
{
public:
virtual void fun()
{
cout<<"A-fun()"<<endl;
}
A()
{}
~A()
{}
private:
int a1;
};
class B:public A
{
public:
virtual void fun1()
{
cout<<"B-fun()"<<endl;
}
B()
{}
~B()
{}
private:
int b1;
};
 
**2**、多继承
          1)子类重写父类虚函数
class A
{
public:
virtual void Afun()
{}
private:
int a1;
};
class B
{
public:
virtual void Bfun()
{}
private:
int b1;
};
class C:public A,public B
{
public:
void Afun()
{}
void Bfun()
{}
private:
int c1;
};
int main()
{
A a;
B b;
C c;
cout<<sizeof(a)<<endl;
cout<<(int*)(&a)<<endl;
cout<<sizeof(b)<<endl;
cout<<(int*)(&b)<<endl;
cout<<sizeof(c)<<endl;
cout<<(int*)(&c)<<endl;
return ;
}

2)子类定义新的虚函数

class A
{
public:
virtual void Afun()
{}
private:
int a1;
};
class B
{
public:
virtual void Bfun()
{}
private:
int b1;
};
class C:public A,public B
{
public:
virtual void Cfun()
{}
private:
int c1;
};
int main()
{
A a;
B b;
C c;
cout<<sizeof(a)<<endl;
cout<<(int*)(&a)<<endl;
cout<<sizeof(b)<<endl;
cout<<(int*)(&b)<<endl;
cout<<sizeof(c)<<endl;
cout<<(int*)(&c)<<endl;
return ;
}

3) 菱形继承

class A
{
public:
void Afun()
{
cout<<"Afun()"<<endl;
}
A()
{}
~A()
{}
private:
int a1;
};
class B:public A
{
public:
void Bfun()
{
cout<<"Bfun()"<<endl;
}
B()
{}
~B()
{}
private:
int b1;
};
class C:public A
{
public:
void Cfun()
{
cout<<"Cfun()"<<endl;
}
private:
int c1;
};
class D:public B,public C
{
public:
void Dfun()
{
cout<<"D-fun()"<<endl;
}
private:
int d1;
};
**3**、虚继承(解决了菱形继承数据冗余和二义性的问题)(虚继承对应要有虚类指针)
          1)单一继承下的虚继承
class A
{
public:
virtual void Afun()
{}
private:
int a1;
};
class B:virtual public A
{
public:
void Afun()
{}
private:
int b1;
};
给B实例化一个对象,它的大小是16,是因为在虚继承过程中,会出现对应的虚类指针

***虚函数的主要作用是为了实现多态机制

class Base
{
virtual void print(void);
};
class Drive1:public Base
{
virtual void print(void);
};
class Drive2:public Base
{
virtual void print(void);
};
int main(int argc,char* argv[])
{
Base* ptr1=new Base;
Base* ptr2=new Drive1;
Base* ptr3=new Drive2;
ptr1->print();//调用base::print()
ptr2->print();//调用Drive1::print()
ptr3->print();//调用Drive2::print()
return ;
}这是一种运行期多态,父类指针唯有在程序运行时才能知道所致的真正类型是什么,这种运行期决议是通过虚函数表来实现的

***使用指针访问虚表

class Base
{
public:
Base(int i)
:base1(i)
{}
virtual void print(void)
{
cout<<"Base::print()"<<endl;
}
virtual void setl(void)
{
cout<<"Base::setl"<<endl;
}
virtual ~Base()
{}
private:
int base1;
};
int main(int argc,char* argv[])
{
Base b();
int* vptrAdree=(int*)(&b);
cout<<"虚函数指针(vptr)的地址是:\t"<<vptrAdree<<endl;
return ;
}
当一个类本身定义了虚函数或者其父类有虚函数时,为了支持多态机制,编译器为该类添加了一个虚函数指针(vptr),虚函数指针一般放在对象内存布局的第一个位置上,这是为了保证在多层继承或多重继承的情况下能以最高效率取到虚表
这个代码的mian()里我们取到了虚函数的地址(vptrAdree),虚函数指针指向虚函数表,虚函数表存的是一系列虚函数的地址,虚函数地址出现的顺序与类中虚函数声明的顺序一致
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

多态&虚函数的更多相关文章

  1. C++ (P199—P211)多态 虚函数 抽象类

    在介绍多态之前,先回忆:赋值兼容原则.虚基类.二义性.派生类如何给基类赋值等知识. 在赋值兼容原则中:父类对象的指针赋给基类的指针或者父类的对象赋给基类的引用,可以通过强转基类的指针或者引用变为父类的 ...

  2. 看懂下面C++代码才说你理解了C++多态虚函数!

    #include <iostream> using namespace std ; class Father { private :  virtual void Say()  //只有添加 ...

  3. OOP 多态/虚函数

    // main.cpp // OOP // 虚函数允许继承层次结构中绝大多数特定版本的成员函数被选择执行,虚函数使多态成为可能. // Created by mac on 2019/4/8. // C ...

  4. C++继承-重载-多态-虚函数

    C++ 继承 基类 & 派生类 一个类可以派生自多个类,这意味着,它可以从多个基类继承数据和函数.定义一个派生类,我们使用一个类派生列表来指定基类.类派生列表以一个或多个基类命名,形式如下: ...

  5. c++学习之多态(虚函数和纯虚函数)

    c++是面向对象语言,面向对象有个重要特点,就是继承和多态.继承之前学过了,就是一种重用类的设计方式.原有的类叫父类,或者基类,继承父类的类叫子类.在设计模式中,我们总是要避免继承,推荐用组合.因为继 ...

  6. C++: 多态 虚函数

    一.多态: 1.多态是什么:具有不同功能的函数可以用同一个函数名 2.静态多态:程序编译时决定,通过函数重载实现. 3.动态多态:程序运行时决定,通过虚函数实现. 二.虚函数: 1.引入目的:可以通过 ...

  7. C++基础 (6) 第六天 继承 虚函数 虚继承 多态 虚函数

    继承是一种耦合度很强的关系 和父类代码很多都重复的 2 继承的概念 3 继承的概念和推演 语法: class 派生类:访问修饰符 基类 代码: … … 4 继承方式与访问控制权限 相对的说法: 爹派生 ...

  8. 【C++基础】 多态 虚函数

    多态:同样的消息被不同类型的对象接收时导致不同的行为.这里“消息”是对类的成员函数的调用,“行为”调用了不同的函数. 分类:①重载多态 ②包含多态……等 实现:编译时的多态  运行时的多态(动态绑定) ...

  9. C++ polymorphism Virtual Function 多态 虚函数

    Polymorphism in C++ https://www.tutorialspoint.com/cplusplus/cpp_polymorphism.htm https://github.com ...

随机推荐

  1. 反序列化失败Failed to deserialize --- local class incompatible: stream classdesc serialVersionUID

    反序列化失败: java.lang.IllegalStateException: Failed to execute CommandLineRunner at org.springframework. ...

  2. 使用JavaMail发送邮件-从FTP读取图片并添加到邮件正文发送

    业务分析: 最近工作需要,需要从FTP读取图片内容,添加到邮件正文发送.发送邮件正文,添加附件采用Spring的MimeMessageHelper对象来完成,添加图片也将采用MimeMessageHe ...

  3. 《Network Security A Decision and Game Theoretic Approach》阅读笔记

    网络安全问题的背景 网络安全研究的内容包括很多方面,作者形象比喻为盲人摸象,不同领域的网络安全专家对网络安全的认识是不同的. For researchers in the field of crypt ...

  4. day43 多表查询和pymysql

    复习 增删改查全语法 # 增 insert into db1.t1(字段2, 字段1, ..., 字段n)|省略 values (值2, 值1, ..., 值n)|(值1, 值2, ..., 值n)[ ...

  5. Cobbler安装CentOS7系统时报错 What do you want do now?

    问题的根源: 在cobbler服务主机中执行了  createrepo --update  /var/www/cobbler/ks_mirror/CentOS-7-x86_64/ 导致的. cobbl ...

  6. 安装64位office时,弹出提示,要求卸载32位office

    运行 regedit,进入到HKEY_CLASSES_ROOT\Installer\Products下,删除0000510开头的项或00002开头项.然后重启计算机. 参考:  https://blo ...

  7. 【python原理解析】python中分片的实现原理及使用技巧

    首先:说明什么是序列? 序列中的每一个元素都会被分配一个序号,即元素的位置,也称为索引:在python中的序列包含:字符串.列表和元组 然后是:什么是分片? 分片就是通过操作索引访问及获得序列的一个或 ...

  8. FortiGate数据流分析 debug flow

    1.工具说明 在防火墙部署中,经常会遇到防火墙接收到了数据包,但并未进行转发.可以通过diagnose debug flow 命令来对数据包的处理过程进行跟踪,可以清晰查看数据包再各个功能模块内的处理 ...

  9. sed原理及使用

    前言 环境:centos6.5 sed版本:GNU sed version 4.2.1 本文的代码都是在这个环境下验证的. 一.简介 sed(Stream Editor)意为流编辑器,是Unix常见的 ...

  10. maven 监理web war 项目