美文网首页C++学习笔记
C++继承与派生,虚函数与多态

C++继承与派生,虚函数与多态

作者: tengmoon | 来源:发表于2015-05-18 14:45 被阅读270次

假设定义了以下的基类和派生类:

class shape
{
    public:
    shape(int a){};             //基类构造
    int length(){};             //基类中与子类重名函数
    void display(){};           //基类中独有
    vitual int area(){};        //基类中虚函数
}

class rectangle:public shape
{
    public:
    rectangle(int);
    int length();
    int area();

}

1. 派生类的定义

rectangle::rectangle(int a):shape(int a){};     //派生类中使用基类构造函数
void rectangle::length()
{
    shape::length();                            //派生类中使用重名的父类函数
    display();                                  //派生类中使用父类中独有函数
}

2. 派生类实例的使用

rectangle rect();
shape theshape();
rect.length();          //调用rectangle::length()
rect.shape::length();   //显式指定调用基类函数shape::length()
rect.display();         //display()被继承,调用shape::display()

3. 对象的成员变量与成员函数的不同

成员变量在对象初始化之后,仍然可以进行赋值,更改。事实上,对对象的任何操作,也仅仅是对它的成员变量进行操作。
成员函数在对象初始化那一刻使确定下来,成员函数是根据该对象的类型进行绑定的,是编译期已经确定的,静态绑定。

各个实例的成员变量的地址是不同的,与实例的首地址有关。
各个实例的成员函数其实是共用的,因为只与他们的类型相关。

成员变量的地址(包括虚表变量)是按照各实例的首地址给的,各实例之间不相同。
成员函数的地址是按照实例的类型给的,各实例间相同。

4. 类型的转换

要区分对象的类型转换对象指针的类型转换:

  1. 实际上,指针的类型可以任意转换,只是指针指向的地址发生变化而已。
  2. 对象的类型转换,实际上是将右值的所有成员变量的值赋给左值。注意:右值的虚表变量不会赋值给左值!
  3. 就地转换,实际上是隐含地调用了一次转换后类型的构造函数,产生了一个临时对象,将这个临时对象作为左值。

    rectangle rect;
    shape shp;
    shp = (shape)rect;          //合法,将rect中与shp相同的那部分成员变量赋给shp
                                //等价于 shp.a = rect.a, shp.b = rect.b
                                // shp.vtable并没有被rect.vtable覆盖! 仍然是原来的。

    rect = (rectangle)shp;      //不合法,因为rect的一些成员变量,shp并没有,所以赋值时要出错
                                //rect.a  = shp.a, rect.b = shp.b,rect.c = shp.?
    rectangle* prect;
    shape* pshp;
    pshp = ▭               //pshp指向了rect的首地址
                                //pshp指向的成员变量是rect的成员变量
                                //(pshp可以指向一些shape类型没有的成员变量)
                                // 但pshp绑定的成员函数还是shape类型的成员函数。
                                //pshp->vtable就是rect.vtable, 但pshp->length()调用的是 shape::length();
    prect = &shp;        //合法,但是没有实际意义

5. 虚成员函数与普通成员函数

上面已提了,一个实例的普通成员函数在编译期已经根据它的类型确实了。而虚函数不是这样的,它的调用是根椐实例的成员变量虚表查到的。

rectangle rect;
shape shp;
shp.area();                 //其实是shp.vtable->area();
rect.area();                //rect.vtable->area();

shape* pshp;
pshp = ▭
pshp->area();               //实际上是pshp->vtable->area(),而pshp->vtable == rect.vtable,所以调用的是 rectangle::area();
pshp->length();             //length是普通的成员函数,根据pshp的类型确定,所以调用的是shape::length();


((shape)rect).area();       //就地转换并调用,相当于下面的的两行代码
shape shp2 = rect;
shp2.area();                //shp2的成员变量被rect的成员变量覆盖,但shp2.vtable并没有变成rect.vtable,仍然调用shape::area();

6. 虚函数的用途:统一形式的调用

shape* pshps = [&triangle(), &rectangel()];
for(auto ipshp: pshps)
    ipshp->area();          //分别调用了各个不同类型实例的area();

相关文章

  • C++继承与派生,虚函数与多态

    假设定义了以下的基类和派生类: 1. 派生类的定义 2. 派生类实例的使用 3. 对象的成员变量与成员函数的不同 ...

  • 2020-07-06----《C++类的学习》

    函数重载:同名不同参。 C++类的特点:封装、继承、多态。 //多态与函数重载是啥关系? 虚函数:和软件架构相关 ...

  • 深刻剖析之c++博客文章

    三大特性 封装、继承、多态 多态 C++ 虚函数表解析C++多态的实现原理 介绍了类的多态(虚函数和动态/迟绑定)...

  • 电商专业学习嵌入式软件开发第五十九天

    C++第五天 今天继续讲多继承,主要讲了继承的构造顺序和菱形继承以及虚函数和动态多态,还讲了异质链表。今天讲的派生...

  • C++语言-多态,纯虚函数,模版函数

    1、虚函数、纯虚函数 需要注意的是,纯虚函数子类是必须继承的,虚函数不是不必须继承的。 2、多态 在C++中默认关...

  • C语言模拟实现多态

    C++的多态分为编译时多态的函数重载和运行时的虚函数. 一个基类类型的指针可以指向派生类的对象, 调用虚函数的时候...

  • 深入研究C++多态(虚函数和虚继承)

    面向对象的三大特性是封装、继承和多态。多态是非常重要的一个特性,C++多态基于虚函数和虚继承实现,本文将完整挖掘C...

  • GeekBand-C++面向对象高级编程(下)-Week2

    对象模型:虚函数表(vtbl)与虚表指针(vptr) 我们知道,C++中,可以通过虚函数来实现多态性,而虚函数是通...

  • 查漏补缺

    C++虚函数: 多态: 静态多态(重载)、动态多态(虚函数) 虚函数 虚函数表:编译器为每个类创建了一个虚函数表...

  • C++多态

    c++的多态总结是:当派生类被强制类型转换为基类时,派生类的虚函数表地址是不会被替换为基类的虚函数表地址的。 运行...

网友评论

    本文标题:C++继承与派生,虚函数与多态

    本文链接:https://www.haomeiwen.com/subject/abqlqttx.html