zoukankan      html  css  js  c++  java
  • C++程序设计POJ》《WEEK6 多态与虚函数》《多态的实现原理》《虚函数表》

    “多态”的关键在于通过基类指针或引用调用
    一个虚函数时,编译时不确定到底调用的是基类还
    是派生类的函数,运行时才确定---- 这叫“动态
    联编”。“动态联编” 底是怎么实现的呢?

    #include<iostream>
    using namespace std;
    class Base {
    public:
        int i;
        virtual void Print()
        {
            cout << "base:print";
        }
    };
    
    class Derived :public Base
    {
    public:
        int n;
        virtual void Print()
        {
            cout << "drived:print" << endl;
        }
    };
    
    int main()
    {
        Derived d;
        cout << sizeof(Base) << "," << sizeof(Derived);
        while (1);
        return 0;
    }
    // 程序运行输出结果: 8, 12
    // 为什么都多了4个字节?

    多态实现的关键--- 虚函数表
    每一个有虚函数的类(或有虚函数的类的派生类)
    都有一个虚函数表,该类的任何对象中都放着虚函数
    表的指针。虚函数表中列出了该类的虚函数地址。
    出来的4个字节就是用来放虚函数表的地址的

    #include<iostream>
    using namespace std;
    class A
    {
    public:
        virtual void Func()
        {
            cout << "A::FUNC" << endl;
        }
    };
    class B :public A
    {
    public:
        virtual void Func()
        {
            cout << "B::func" << endl;
        }
    };
    int main()
    {
        A a;
        A *pa = new B();
        //64位程序指针为8字节
        long long * p1 = (long long *)&a;
        long long * p2 = (long long *)pa;
        *p2 = *p1; // 更改虚函数表的内容
        pa->Func();
        while (1);
        return 0;
    
    }
    // B::Func
    // A::Func

     虚析构函数

    只要基类是虚析构函数,那么派生类默认都是虚析构函数

    虚析构函数通过基类指针删除掉派生类对象


    通过基类的指针删除派生类对象时,通常情况下只调用基类的析构
    函数

    但是,删除一个派生类的对象时,应该先调用派生类的析构函
    数,然后调用基类的析构函数。

    解决办法:把基类的 析构函数声明为 virtual

    派生类的析构函数可以 virtual 不进行声明

    通过基类的指针删除派生类对象时,首先调用派生类的析构函
    数,然后调用基类的析构函数

    一般来说,一个类如果定义了虚函数,则应该将析构函数也定义成
    虚函数。或者,一个类打算作为基类使用,也应该将析构函数定义
    成虚函数。

    注意: 不允许以虚函数作为构造函数

    纯虚函数和抽象类

    纯虚函数: 没有函数体的虚函数
    class A {
    private: int a;
    public:
    virtual void Print( )  = 0 ;// 纯虚函数

    void fun() { cout << "fun"; }
    };


    包含纯虚函数的类叫抽象类

    抽象类只能作为基类来派生新类使用,不能创建抽象类的对象

    抽象类的指针和引用可以指向由抽象类派生出来的类的对象
    A a ;
    // 错, A 是抽象类,不能创建对象
    A * pa ;
    // 可以定义抽象类的指针和引用
    pa = new A ;
    错误 , A 是抽象类,不能创建对象

    在抽象类的成员函数内可以调用纯虚函数,但是在构造函数或析构函数内部
    不能调用纯虚函数。

    如果一个类从抽象类派生而来,那么当且仅当它实现了基类中的所有纯虚函
    数,它才能成为非抽象类。

  • 相关阅读:
    redis基础
    Django Meta
    Django Query
    Django FileFieldManage
    Django Managers管理器
    Django 模型
    Pytables h5py
    python 高级部分
    Python和HDF 5大数据应用
    是时候放弃pipeline 模型 ?
  • 原文地址:https://www.cnblogs.com/focus-z/p/11080080.html
Copyright © 2011-2022 走看看