• 构造函数、析构函数能否定义成虚函数以及在其内能够发生多态行为


    构造函数是否可以成为虚函数?
    构造函数不能成为虚函数
    -C++中的多态是由指向虚函数表的指针来完成的,那么指向虚函数表的指针是由编译器创建的,同时也是由编译器进行初始化。那什么时候对虚函数表指针进行初始化呢?
    -在构造函数执行结束后,虚函数表指针才会正确的初始化

    析构函数是否可以成为虚函数?
    -建议在设计类时将析构函数声明为虚函数

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class Base
    {
    public:
        Base()
        {
            cout << "Base()" << endl;
        }
    
         ~Base()
        {
    
            cout << "~Base()" << endl;
        }
    };
    
    
    class Derived : public Base
    {
    public:
        Derived()
        {
            cout << "Derived()" << endl;
    
        }
    
    
        ~Derived()
        {
    
            cout << "~Derived()" << endl;
        }
    };
    
    
    int main()
    {
        Base* p = new Derived();
    
        // ...
    
        delete p;//在这里我们期望的是先调用子类的析构函数,再调用父类的析构函数。即期望打印:~Derived()  ~Base()
    
        return 0;
    }

     在这里只调用了父类的析构函数。

    delete p,此时删除的是一个父类的指针,没有将析构函数声明为virtual,因此在这种情况下,编译器直接根据指针p的类型来决定调用哪个析构函数,因此就直接调用了父类的析构函数

    如果将父类的析构函数声明为virtual,编译器就不会简单暴力的根据指针p的类型来调用父类的析构函数还是子类的析构函数。这时它又是怎样处理的?
    由于析构函数是虚函数,所以在执行delete p的时候,编译器根据指针所指向的实际对象来决定如何调用析构函数。这是什么,多态啊。这就是将虚函数声明为虚函数的意义。

    class Base
    {
    public:
        Base()
        {
            cout << "Base()" << endl;
        }
    
        virtual ~Base()
        {
    
            cout << "~Base()" << endl;
        }
    };

    在工程开发中,通常将父类中的析构函数声明为虚函数,如果不这样做,有可能会发生内存泄露。因为它会跳过子类析构函数的调用,当子类析构函数中有释放内存的操作时,就发生内存泄露了。

    在构造函数中不可能发生多态行为
    -在构造函数执行时,虚函数表指针未被正确初始化
    析构函数中不可能发生多态行为
    -在析构函数执行时,虚函数表指针已经被摧毁

    构造函数和析构函数中不能发生多态行为,只能调用当前类中定义的函数版本。

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class Base
    {
    public:
        Base()
        {
            cout << "Base()" << endl;
    
            func();
        }
    
        virtual void func()
        {
            cout << "Base::func()" << endl;
        }
    
        virtual ~Base()
        {
            func();
    
            cout << "~Base()" << endl;
        }
    };
    
    
    class Derived : public Base
    {
    public:
        Derived()
        {
            cout << "Derived()" << endl;
    
            func();
        }
    
        virtual void func()
        {
            cout << "Derived::func()" << endl;
        }
    
        ~Derived()
        {
            func();
    
            cout << "~Derived()" << endl;
        }
    };
    
    
    int main()
    {
        Base* p = new Derived();
    
        // ...
    
        delete p;
    
        return 0;
    }
  • 相关阅读:
    模板之st表
    codevs 1163 访问艺术馆
    noip提高组2000 乘积最大
    [HNOI2008]越狱(luogu P3197)
    [ZJOI2009]假期的宿舍(luogu P2055)
    noip普及组2013 车站分级(luogu P1983)
    [HNOI2010]平面图判定
    sql中对于case when...then...else...end的写法和理解
    java中,去除空白的方法
    关于debug时的一些操作
  • 原文地址:https://www.cnblogs.com/-glb/p/11973480.html
Copyright © 2020-2023  润新知