C++ 继承&多态

原创 2016年05月30日 13:35:10

继承&多态

· 访问限定符

*继承访问控制的作用是将继承下来的成员在派生类域内的属性改变而和原本基类的成员访问控制符关。

 所有的基类private成员在派生类里是不可见,但它确确实实被继承下来了。

 基类的protected成员只对继承它的派生类可见,在类外不可使用


· 派生类列表

  在定义派生类的时候我们必须写出派生类列表,但在声明处不可写。


1.虚函数的使用(多态的实现)

#include<iostream>
using namespace std;
class Base
{
private:
     int _base ;
public:
     Base()
            :_base (0)
     {}
     virtual void show()
     {
            cout << "Base::show()" << endl ;
     }
     //....
};
class D :public Base
{
public:
     D()
            :_d (1)
     {}
     void show()
     {
            cout << "D::show()" << endl ;
     }

private:
     int _d ;
};
void Print (Base *pb)
{
     pb-> show();
}
int main ()
{
     Base b;
     D d;
     Print(& b);
     Print(& d);
     getchar();
     return 0;
}


wKioL1btOM-x6FbyAAAJ7xNtKBI508.png

*通过传参的不同使得show函数的输出结果不同,实现的原理是:虚函数表(动态绑定)

*动态绑定:函数的运行版本由实参决定,在函数运行时才进行选择,又称运行时绑定

*规则:基类通常都需要定义一个虚析构函数,无论是否在后面用到

*成员函数如果没有被声明为虚函数并且不是静态函数,那它的解析过程发生在编译阶段而不是运行阶段

*每个类控制自己的成员初始化,不要使用派生类直接初始化基类成员

*派生类必须对它内部重新定义的虚函数进行声明

*任何除了构造函数以外的非静态函数都可以是虚函数


2.虚函数表

 a.单继承

  如上例中代码示,单继承时Base的对象模型如下

wKioL1btOPewHXhWAAAWc8Njv0M657.png

 D的对象模型如下

wKiom1btOJXz7HUgAAAWf_gvT9M244.png

 b.多继承 

#include<iostream>
using namespace std;
typedef void (*PTR)();
class Base
{
private:
     int _base ;
public:
     Base()
            :_base (0)
     {}
     virtual void show()
     {
            cout << "Base::show()" << endl ;
     }
     //...
};
class Base2
{
private:
     int _base2 ;
public:
     Base2()
            :_base2 (2)
     {}
     virtual void show()
     {
            cout << "Base2::show()" << endl ;
     }
     virtual void fun2()
     {
            cout << "Base2::fun2()" << endl ;
     }
     //...
};
class D :public Base,public Base2
{
public:
     D()
            :_d (1)
     {}
     void show()
     {
            cout << "D::show()" << endl ;
     }
     void fun2()
     {
            cout << "D::fun2()" << endl ;
     }
     virtual void fun3()
     {
            cout << "D::fun3()" << endl ;
     }
     virtual void fun4()
     {
            cout << "D::fun4()" << endl ;
     }
private:
     int _d ;
};
void PrintVT (int p )
     //实参是每个类存储虚函数指针的地址,解引用之后代表该类的虚函数指针
{
     PTR ptr = NULL;
     //现在让pi能访问类的虚函数指针
     int *pi = (int *)p;
     int i = 0;
     while (pi [i ])
     {
            ptr = (PTR)pi[i];
            ptr();
            i++;
     }
}
int main ()
{
     //Base b;
     //Base2 b2;
     D d;
     //PrintVT(*(int *)&b);
     //cout << "--------------------" << endl;
     //PrintVT(*(int *)&b2);
     //cout << "--------------------" << endl;
     PrintVT(*( int *)&d );
     cout << "--------------------" << endl ;
     getchar();
     return 0;
 }


 如上述代码,我们发现多继承的虚函数表和单继承由很大的不同之处

 在此不再赘述两个基类的虚表,我们来看派生类的对象模型

wKiom1btOGeSUmyqAAAfqhZS5ZI278.png

 spacer.gif

*我们发现在派生类中有两个虚函数表,并且派生类自己的虚函数被存入了第一个虚函数表

上述代码运行的结果是

wKioL1btOYqgjYTEAAAXcyFD6Kg565.png


tips:

   *在一个对象中继承自基类的部分和派生类的自定义部分不一定是连续存储的

   *如果在基类里定义了一个静态成员那么这个成员是唯一定义的,只存在一个实例

   *含有关键字final的类不可以作为基类被继承

   *动态绑定基于给用基类的指针或者引用绑定对象。除了内置指针外智能指针也是可以做到这样的     类     型转换的

          

C++的多态性:我们把具有继承关系的多个类型称为多态类型,因为我们可以使用这些类型的多种形式而无须在意他们的差异


覆盖:派生类重新定义了基类的虚函数并且他们的函数名,参数列表和返回值都必须相同但是协变的返              回值必须不同。

隐藏:派生类重新中定义了基类中同名的函数(非虚函数和静态函数)此时基类中的同名函数被隐藏

重载:在同一个作用域内我们定义了几个同名函数他们通过参数列表来区分彼此称为重载


*我们可以在支持C++11的编译器中给覆盖加上override关键字,那么我们在编写该函数时编译器会检查   它形式的正确性,保证我们的调试变得更加简单


本文出自 “Zimomo” 博客,请务必保留此出处http://zimomo.blog.51cto.com/10799874/1752936

版权声明:本文为博主原创文章,未经博主允许不得转载。

【c++知识归纳】继承与多态(一)

c++是基于面向对象的编程语言,面向对象的三大特性为:封装、继承和多态。本文将我对继承与多态的理解进行了总结归纳,这部分内容对于学习c++编程语言是非常重要的,文章加入我的个人理解,希望能给大家带来帮...
  • XHfight
  • XHfight
  • 2016年08月24日 02:45
  • 1423

C++精进篇(十)之―封装、继承、多态及访问权限及对象创建详解

面向对象的三个基本特征是:封装、继承、多态。其中,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用! ...
  • fanyun_01
  • fanyun_01
  • 2016年03月26日 09:21
  • 1363

C语言模式实现C++继承和多态

这个问题主要考察的是C和C++的区别,以及C++中继承和多态的概念。C和C++的区别C语言是面向过程的语言,而C++是面向对象的过程。什么是面向对象和面向过程? 面向过程就是分析解决问题的步骤,然后用...
  • wenqiang1208
  • wenqiang1208
  • 2017年07月28日 12:36
  • 707

c++面向对象三大特征封装、继承和多态知识总结

面向对象三大特征:封装,继承,多态; 一、封装:该公开的就公开话,该私有的就隐藏掉,主要是由public,private实现;作用是便于分工和分模块,防止不必要的扩展; 二、继承:就是一种传承,可以把...
  • uestclr
  • uestclr
  • 2016年06月05日 18:23
  • 2910

c++——多态、继承、运算符重载综合例子代码

#include #include using namespace std; class A { private: char *name; public: A(char *n); ...
  • qq_18860653
  • qq_18860653
  • 2017年02月09日 08:58
  • 252

C++中的多态和派生继承

本文分别节选转自: http://blog.csdn.net/w3031213101/article/details/5420486 http://www.cnblogs.com/fzhe/arch...
  • jasonsungblog
  • jasonsungblog
  • 2015年10月11日 23:08
  • 784

C++总结6——继承与多态的笔试题

1———————————————- #include using namespace std; class Base { public: Base(int data):_ma(data)...
  • wendy_keeping
  • wendy_keeping
  • 2017年07月17日 02:01
  • 304

C/C++继承类的多态表现

学过C++和Java的人都知道,他们二者由于都可以进行面向对象编程,而面向对象编程的三大特性就是封装、继承、多态,所有今天我们就来简单了解一下C++和Java在多态这方面的不同。 首先我们各看一个案...
  • dongxianfei
  • dongxianfei
  • 2016年12月29日 16:14
  • 816

C++中的封装、继承、多态

C++中的封装、继承、多态
  • fengbingchun
  • fengbingchun
  • 2014年03月30日 12:52
  • 4144

C++里的继承和多态(上)

继承 1、私有继承:基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问。       公有继承:基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的访问权限,而基...
  • lemonwxj
  • lemonwxj
  • 2016年04月20日 17:05
  • 914
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++ 继承&多态
举报原因:
原因补充:

(最多只允许输入30个字)