C++之虚函数和虚继承

首先来看一个实例

 1 #include <iostream>
 2 #include<stdio.h>
 3 #include<stdlib.h>
 4 #include<assert.h>
 5 using namespace  std;
 6 class A
 7 {
 8 public:
 9     A(){ cout << "A构造函数" << endl;  }
10     ~A(){ cout << "A析构函数" << endl; }
11     virtual void print(){ cout << "父类的虚函数" << endl; }
12     void fun(){ cout << "fun a" << endl; }
13     virtual void V_fun(){ cout << "virtual fun a" << endl; }
14 };
15 class B :virtual public A
16 {
17 public:
18     B(){ cout << "B构造函数" << endl;}
19     ~B(){ cout << "B析构函数" << endl;}
20     void fun(){ cout << "fun b" << endl; }
21     virtual void print(){ cout << "B派生类实现父类的纯虚函数" << endl; }
22     virtual void V_fun(){ cout << "virtual fun b" << endl; }
23 };
24 class C:virtual public A
25 {
26 public:
27     C(){ cout << "C构造函数" << endl; }
28     ~C(){ cout << "C析构函数" << endl; }
29     void fun(){ cout << "fun c" << endl; }
30     //virtual void print(){ cout << "C派生类实现父类的纯虚函数" << endl; }
31 };
32 class D :public B,public C
33 {
34 public:
35     D(){ cout << "D构造函数" << endl; }
36     ~D(){ cout << "D析构函数" << endl; }
37 };
38 int main()
39 {
40     A *a = new B();
41     a->fun();
42     a->V_fun();
43     a->print();
44     getchar();
45     return 0;
46 }

虚函数:

函数声明和定义和普通的类成员函数一样,只是在返回值之前加入了关键字“virtual”声明为虚函数。而虚函数是实现多态的重要手段,意思是只有对虚函数的调用才能动态决定调用哪一个函数,这是相对于普通成员函数而言的,普通的成员函数在编译阶段就能确定调用哪一个函数。

基类A有两个成员函数fn和v_fn,派生类B继承自基类A,同样实现了两个函数,然后在main函数中用A的指针指向B的实例(向上转型,也是实现多态的必要手段),然后分别调用fn和v_fn函数。结果是“fn in A"和"virtual fn in B"。这是因为fn是普通成员函数,它是通过类A的指针调用的,所以在编译的时候就确定了调用A的fn函数。而v_fn是虚函数,编译时不能确定,而是在运行时再通过一些机制来调用指针所指向的实例(B的实例)中的v_fn函数。假如派生类B中没有实现(完全一样,不是重载)v_fn这个函数,那么依然会调用基类类A中的v_fn;如果它实现了,就可以说派生类B覆盖了基类A中的v_fn这个虚函数。这就是虚函数的表现和使用,只有通过虚函数,才能实现面向对象语言中的多态性。

虚继承:

为了解决从不同途径继承来的同名的数据成员在内存中有不同的拷贝造成数据不一致问题,将共同基类设置为虚基类。这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数名也只有一个映射。这样不仅就解决了二义性问题,也节省了内存,避免了数据不一致的问题。
class 派生类名:virtual 继承方式  基类名
virtual是关键字,声明该基类为派生类的虚基类。
在多继承情况下,虚基类关键字的作用范围和继承方式关键字相同,只对紧跟其后的基类起作用。
声明了虚基类之后,虚基类在进一步派生过程中始终和派生类一起,维护同一个基类子对象的拷贝。

语法:

class 派生类: virtual 基类1,virtual 基类2,...,virtual 基类n

{

...//派生类成员声明

};

执行顺序

首先执行虚基类的构造函数,多个虚基类的构造函数按照被继承的顺序构造;

执行基类的构造函数,多个基类的构造函数按照被继承的顺序构造;

执行成员对象的构造函数,多个成员对象的构造函数按照申明的顺序构造;

执行派生类自己的构造函数;

析构以与构造相反的顺序执行;

解决了二义性问题,也节省了内存,避免了数据不一致的问题。

C++虚函数解析:看陈大神的专栏吧http://blog.csdn.net/haoel/article/details/1948051/

时间: 2024-08-03 14:22:27

C++之虚函数和虚继承的相关文章

C++ 虚函数和虚继承浅析

本文针对C++里的虚函数,虚继承表现和原理进行一些简单分析,有希望对大家学习C++有所帮助.下面都是以VC2008编译器对这两种机制内部实现为例. 虚函数 以下是百度百科对于虚函数的解释: 定义:在某基类中声明为 virtual 并在一个或多个派生类中被重新定 义的成员函数[1] 语法:virtual 函数返回类型 函数名(参数表) { 函数体 } 用途:实现多态性,通过指向派生类的基类指针,访问派生类中同名覆盖成员函数 函数声明和定义和普通的类成员函数一样,只是在返回值之前加入了关键字"vir

虚函数和虚拟继承的内存分布

一.虚函数 (1)C++中的虚函数的主要作用:实现了多态的机制. (2)多态:用父类型的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有"多种形态",这是一种泛型技术.所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法.比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议. (3)多态要基于函数重载,所以如果子类没有重载父类的虚函数那是一件毫无意义的事情. 二.虚函数表 1.虚函数表:虚函数表C+

C++之易混淆知识点四---虚函数与虚继承

C++面向对象中,虚函数与虚继承是两个完全不同的概念. 一.虚函数 C++程序中只要类中含有虚拟函数,编译程序都会为此类生成一个对应的虚拟函数跳转表(vtbl),该虚拟函数跳转表是一个又若干个虚拟函数体入口地址组成的一个线性表.派生类的虚拟函数跳转表的前半部分由父类的vtbl得出,但是里面的内容不一定相同,后半部分则对应着自己新定义的虚拟函数. class Employee { protected: char *Name; int Age; public: void changeAge(int

C++之虚函数与虚继承详解

准备工作 1.VS2012使用命令行选项查看对象的内存布局 微软的Visual Studio提供给用户显示C++对象在内存中的布局的选项:/d1reportSingleClassLayout.使用方法很简单,直接在[项目P]选项下找到"visual属性"后点击即可.切换到cpp文件所在目录下输入如下的命令即可 c1 [filename].cpp /d1reportSingleClassLayout[className] 其中[filename].cpp就是我们想要查看的class所在的

C++纯虚函数、虚函数、实函数、抽象类,重载、重写、重定义

首先,面向对象程序设计(object-oriented programming)的核心思想是数据抽象.继承.动态绑定.通过数据抽象,可以使类的接口与实现分离,使用继承,可以更容易地定义与其他类相似但不完全相同的新类,使用动态绑定,可以在一定程度上忽略相似类的区别,而以统一的方式使用它们的对象. 虚函数的作用是实现多态性(Polymorphism),多态性是将接口与实现进行分离,采用共同的方法,但因个体差异而采用不同的策略.纯虚函数则是一种特殊的虚函数.虚函数联系到多态,多态联系到继承. 一.虚函

C++虚函数及虚函数表解析

一.背景知识(一些基本概念) 虚函数(Virtual Function):在基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数.纯虚函数(Pure Virtual Function):基类中没有实现体的虚函数称为纯虚函数(有纯虚函数的基类称为虚基类).C++  “虚函数”的存在是为了实现面向对象中的“多态”,即父类类别的指针(或者引用)指向其子类的实例,然后通过父类的指针(或者引用)调用实际子类的成员函数.通过动态赋值,实现调用不同的子类的成员函数(动态绑定).正是因为这种

C++虚函数与虚析构函数

在类中,有两个与众不同的成员函数,那就是构造函数和析构函数.当构造函数与析构函数遭遇继承和多态,它们的运行状况又会出现什么变化呢? 多态性是在父类或各子类中执行最合适成员函数.一般来说,只会选择父类或子类中的某一个成员函数来执行.这可给析构函数带来了麻烦!如果有的资源是父类的构造函数申请的,有的资源是子类的构造函数申请的,而虚函数只允许程序执行父类或子类中的某一个析构函数,岂不是注定有一部分资源将无法被释放?为了解决这个问题,虚析构函数变得与众不同. 下面我们就来给析构函数的前面加上保留字vir

C++ 虚函数&amp;纯虚函数&amp;抽象类&amp;接口&amp;虚基类(转)

http://www.cnblogs.com/fly1988happy/archive/2012/09/25/2701237.html 1. 多态 在面向对象语言中,接口的多种不同实现方式即为多态.多态是指,用父类的指针指向子类的实例(对象),然后通过父类的指针调用实际子类的成员函数. 多态性就是允许将子类类型的指针赋值给父类类型的指针,多态是通过虚函数实现的. 多态可以让父类的指针有“多种形态”,这是一种泛型技术.(所谓泛型技术,就是试图使用不变的代码来实现可变的算法). 2. 虚函数 2.1

虚函数与虚析构函数原理

----------------siwuxie095 关于虚函数和虚析构函数的实现原理,因为涉及到 函数指针, 所以先介绍什么是函数指针 函数指针 如果通过一个指针指向对象,就称其为 对象指针,指针除了可以 指向对象之外,也可以指向函数,就称其为 函数指针 函数的本质,其实就是一段二进制的代码,它写在内存中, 可以通过指针来指向这段代码的开头,计算机就会从开头 一直往下执行,直到函数的结尾,并通过指令返回回来 如果有这么 5 个函数指针,它们所存储的就是 5 个函数的函数地址,当 使用时,如:使

C++虚函数与虚函数表

多态性可分为两类:静态多态和动态多态.函数重载和运算符重载实现的多态属于静态多态,动态多态性是通过虚函数实现的. 每个含有虚函数的类有一张虚函数表(vtbl),表中每一项是一个虚函数的地址, 也就是说,虚函数表的每一项是一个虚函数的指针. 没有虚函数的C++类,是不会有虚函数表的. 两张图: 简单例子: 1 #include <iostream> 2 #include <windows.h> 3 4 using namespace std; 5 6 class base 7 { 8