• C++程序设计方法3:虚函数


    向上映射与向下映射

    派生类对象转换成基类对象,称为向上映射。

    而基类对象转换成派生类对象,称为向下映射;

    向上映射可由编译器自动完成,是一种隐式的自动类型转化;

    凡是接受基类对象的地方(如函数参数)都可以使用派生类对象,编译器会自动将派生类

    转化为基类对象以便使用;

    #include <iostream>
    using namespace std;
    
    class Base
    {
    public:
        void print()
        {
            cout << "Base::print()" << endl;
        }
    };
    
    class Derive :public Base
    {
    public:
        void print()
        {
            cout << "Derive:print()" << endl;
        }
    };
    
    void fun(Base obj)
    {
        obj.print();
    }
    
    int main()
    {
        Derive d;
        d.print();
        fun(d);//Base::print()自动转化为基类的对象
        return 0;
    }

    虚函数

    对于被派生类重写的成员函数,若它在基类中被声明为虚函数,则通过基类指针或者引用

    调用该成员函数时,编译器将根据所指向对象的实际类型决定是调用基类中的函数还是派生类中重写的函数;

    class Base

    {

    public:

      virtual 返回类型 函数名(形式参数);//虚函数

    };

    若某个成员函数在基类中声明为虚函数,当派生类重新写他时,无论是否声明为虚函数,

    该成员函数都可以仍然是虚函数;

    #include <iostream>
    using namespace std;
    
    class Base
    {
    public:
        virtual void print()
        {
            cout << "Base::print()" << endl;
        }
    };
    
    class Derive : public Base
    {
    public:
        void print()
        {
            cout << "Derive::print()" << endl;
        }
    };
    
    void fun(Base& obj)
    {
        obj.print();//obj是Base类对象的引用
    }
    
    int main()
    {
        Derive d;
        d.print();
        fun(d);
        return 0;
    }

    虚析构函数的使用例子:

    #include <iostream> using namespace std; class B { public: virtual void show() { cout << "B.show() "; } virtual ~B() { cout << "~B() "; } }; class D : public B { public: void show() { cout << "D.show() "; } ~D() { cout << "~D() "; } }; void test(B* ptr) { ptr->show(); } int main() { B * ptr = new D; test(ptr); delete ptr; }

    禁止重写的虚函数

    使用final关键字修饰的虚函数,派生类不可以对它进行重写,改变函数的定义或者行为;

    在派生类的过程中,final可以在继承关系链的中途设置,禁止后续派生类对指定虚函数的重写;

    class A

    {

    public:

      virtual void fun() = 0;

    };

    classB:public A

    {

      public:

        void fun() final;//到此为止,后续的子类不可以再重新写此接口函数

    };

    class C:public B

    {

      public:

        void fun();//无法通过编译

    };

    怕什么真理无穷,进一寸有一寸的欢喜。---胡适
  • 相关阅读:
    数据库迁移到Amazon RDS 的问题
    排序算法之希尔排序
    第一个 Shell脚本
    排序算法之直接插入排序
    当前工作参考
    cerr
    阿里云典型应用案例
    云服务引擎ACE
    阿里云SLB
    指针使用注意事项
  • 原文地址:https://www.cnblogs.com/hujianglang/p/6642606.html
Copyright © 2020-2023  润新知