C++之virtual析构函数

3500阅读 1评论2013-06-30 scq2099yt
分类:C/C++

        C++明确指出:当derived class对象经由一个base class指针被删除,而该base class带着一个non-virtual析构函数,其结果未定义——实际执行时通常发生的是对象的derived成分没被销毁,而base成分会被销毁,于是造成一个诡异的“局部销毁”对象,从而导致资源泄漏,比如:
        class base{
        public:
                base(){printf("base con\n");}
                ~base(){printf("base der\n");
                ...
        };

        class derived : public base{
        public:
                derived() {printf("derived con\n");}
                ~derived(){printf("derived der\n");}
                ...
        };

        int main()
        {
                base *b = new derived;
                delete b;
                return 0;
        }
        输出结果是:
        base con
        derived con
        base der
        解决这个问题方法很简单:给base class一个virtual析构函数即可,比如:
        class base{
        public:
                base(){printf("base con\n");}
                virtual ~base(){printf("base der\n");
                ...
        };

        class derived : public base{
        public:
                derived() {printf("derived con\n");}
                ~derived(){printf("derived der\n");}
                ...
        };

        int main()
        {
                base *b = new derived;
                delete b;
                return 0;
        }
        输出结果是:
        base con
        derived con
        derived der
        base der
        任何class只要带有virtual函数都几乎确定应该也有一个virtual析构函数,如果class不含有virtual函数,通常表示其并不意图被用作一个base class,此时,如果令其析构函数为virtual往往是一个馊主意,比如:
        class Point{        //一个二维空间点
        public:
                Point()(int x, int y);
                ~Point();
        private:
                int x;
                int y;
        };
        如果int占用32 bits,那么Point对象可塞入一个64 bits缓存器中,更有甚者,这个Point对象可被当做一个”64 bits量“传给C语言撰写的函数,然而当Point的析构函数是virtual时,对象体积发生变化,增加了32 bits的vptr,大小增至96 bits,而C语言中没有vptr,因此,也就无法传递了,除非明确补偿vptr,这样也就不再具有可移植性了。
        polymorphic(带多态性质的)base classes应该声明一个virtual析构函数。如果class带有任何virtua函数,它就应该拥有一个virtual析构函数。
        classes的设计目的如果不作为base classes使用,或不是为了具备多态性(polymorphically),就不该声明virtual析构函数。
        
        
        



上一篇:C++之对象初始化
下一篇:C++之绝不在构造和析构过程中调用virtual函数

文章评论