正在加载……
专注、离线、切勿分心
       虽然构造函数不能被定义成虚函数,但析构函数可以定义为虚函数,一般来说,如果类中定义了虚函数,析构函数也应被定义为虚析构函数,尤其是类内有申请的动态内存,需要清理和释放的时候。如果析构函数是非虚的,释放时会造成child类的析构函数得不到执行,从而内存泄漏。析构函数定义为虚析构函数,这样base类和child类的析构函数都得到了执行,避免了内存泄漏。



虚析构函数调用规则:
      ★如果有一个基类的指针指向派生类的对象,并且想通过该指针delete派生类对象,系统将只会执行基类的析构函数,而不会执行派生类的析构函数。为避免这种情况的发生,往往把基类的析构函数声明为虚的,此时,系统将先执行派生类对象的析构函数,然后再执行基类的析构函数。
      ★如果基类的析构函数声明为虚的,派生类的析构函数也将自动成为虚析构函数,无论派生类析构函数声明中是否加virtual关键字。

#include<iostream>
using namespace std;
class Base
{
        public:
                Base():_str(new char[32])
                {
                        cout<<"Base()"<<endl;
                }
                ~Base()
                {
                        delete []_str;
                        cout<<"~Base()"<<endl;
                }
        private:
                char* _str;
};
class Derived:public Base
{
        public:
                Derived():Base(),_mstr(new char[32])
                {
                        cout<<"Derived()"<<endl;
                }
                ~Derived()
                {
                        delete []_mstr;
                        cout<<"~Derived()"<<endl;
                }
        private:
                char* _mstr;
};
int main()
{
        Base* p = new Derived;
        delete p;
        return 0;
}

#include<iostream>
using namespace std;
class Base
{
        public:
                Base():_str(new char[32])
                {
                        cout<<"Base()"<<endl;
                }
                virtual ~Base()  //虚析构函数
                {
                        delete []_str;
                        cout<<"~Base()"<<endl;
                }
        private:
                char* _str;
};
class Derived:public Base
{
        public:
                Derived():Base(),_mstr(new char[32])
                {
                        cout<<"Derived()"<<endl;
                }
                ~Derived()  //虚析构函数,virtual从继承结构中得来
                {
                        delete []_mstr;
                        cout<<"~Derived()"<<endl;
                }
        private:
                char* _mstr;
};
class DDerived:public Derived
{
        public:
                DDerived():Derived(),_mmstr(new char[32])  //构造函数只要调用自己直接父类的构造函数就好了
                {
                        cout<<"DDerived()"<<endl;
                }
                ~DDerived()  //虚析构函数,virtual从继承结构中得来
                {
                        delete []_mmstr;
                        cout<<"~DDerived()"<<endl;
                }
        private:
                char* _mmstr;
};

int main()
{
        Base* p = new Derived;
        delete p;
        cout<<endl;

        Derived* p1 = new DDerived;
        delete p1;
        cout<<endl;

        Base* p2 = new DDerived;
        delete p2;
        cout<<endl;

        DDerived* p3 = (DDerived*)new Base;
        delete p3;
        return 0;
}

#include <iostream>
using namespace std;
class Base0
{
public:
        Base0(){cout << "Base0()" << endl;        }
        ~Base0(){cout << "~Base0() " << endl;        }
        virtual void func1()
        {        cout << "Base0::func1()" << endl;        }
        virtual void func2()
        {        cout << "Base0::func2()" << endl;        }
};
class Base1 : public Base0
{
public:
        Base1()
        {
                func1();
                cout << "Base1()" << endl;
        }       
        virtual void func1()
        {        cout << "Base1::func1()" << endl;  }
        virtual void func2()
        {        cout << "Base1::func2()" << endl;        }
        ~Base1()
        {
                func2();
                cout << "~Base1()" << endl;
        }
};
class Sub : public Base1
{
public:
        Sub()
        {
                func1();
                cout << "Sub()" << endl;     
        }
        ~Sub()
        {        cout << "~Sub()" << endl;        }
#if 1  //0
        virtual void func1()
        {       cout << "Sub::func1()" << endl;      }
#endif
        virtual void func2()
        {       cout << "Sub::func2()" << endl;      }
};
int main(void)
{
        Sub sub;
        return 0;
}
//1


//0

// 本类没有func1,就去调用父类的

基派生的二义性:

#include <iostream>
using namespace std;
class Base
{
        public:
                Base():_pdata(new char[1])
                {  cout<<"Base()"<<endl;  }
                virtual ~Base()
                { 
                        cout<<"~Base()"<<endl;
                        delete []_pdata;
                }
        private:
                char * _pdata;
};
class Child : public Base
{
        public:
                Child():Base(),_pdata2(new char[1])
                {  cout<<"Child()"<<endl;  }
                ~Child()
                {
                        cout<<"~Child()"<<endl;
                        delete []_pdata2;
                }
        private:
                char * _pdata2;
};
int main()
{
        Base * pb = new Child;
        delete pb;
        cout<<"sizeof(Base)="<<sizeof(Base)<<endl;
        cout<<"sizeof(Child)="<<sizeof(Child)<<endl;
}
//基派生二义性
#include <iostream>
using namespace std;
class A
{
        public:
                virtual void a()
                {   cout<<"A::a()"<<endl;   }
                virtual void b()
                {   cout<<"A::b()"<<endl;   }
                virtual void c()
                {   cout<<"A::c()"<<endl;   }
};
class B
{
        public:
                virtual void a()
                {   cout<<"B::a()"<<endl;   }
                virtual void b()
                {   cout<<"B::b()"<<endl;   }
                void c()
                {   cout<<"B::c()"<<endl;   }
                void d()
                {   cout<<"B::d()"<<endl;   }
};
class C : public A, public B
{
        public:
                virtual void a()
                {   cout<<"C::a()"<<endl;   }
                void c()
                {   cout<<"C::c()"<<endl;   }
                void d()
                {   cout<<"C::d()"<<endl;   }
};
int main()
{
        C c;
        //c.b();  //A,B都有b(),无法确定使用哪个,二义性  解决办法,c.B::b()
        A *pa = &c;
        pa->a();  //C::a()
        pa->b();  //A,B都有b(),采用静态联编,A* 指针,所以A::b();
        pa->c();  //c()在A中虚函数,B中普通函数,C中重定义,输出由指针的类型决定,
                      //由于A中为虚函数,根据规则,调用C::c()
        cout<<endl;
        B *pb = &c;
        pb->a();   //C::a()
        pb->b();   //无法确定调用版本,静态联编,pb类型为B,所以调用B::b()
        pb->c();   //取决于pb类型B,调用B::c()
        pb->d();   //B,C都为普通函数,C隐藏了基类中的d(),但是指针pb为B类型,调用B::d()
        cout<<"pa = "<<pa<<endl;
        cout<<"pb = "<<pb<<endl;
        cout<<"sizeof(A) = "<<sizeof(A)<<endl;
        cout<<"sizeof(B) = "<<sizeof(B)<<endl;
        cout<<"sizeof(C) = "<<sizeof(C)<<endl;   //继承两个基类,基类的虚函数表都要继承过来
        cout<<endl;
        C *pc = &c;
        cout<<"pc = "<<pc<<endl;
        pc->a();   //C::a()
        pc->c();   //C::c()
        pc->d();   //C::d()
        return 0;
}





#include<iostream>
using namespace std;
class A
{
        public:
                virtual void a()
                {
                        cout<<"a() in A"<<endl;
                }
                virtual void b()
                {
                        cout<<"b() in A"<<endl;
                }
                virtual void c()
                {
                        cout<<"c() in A"<<endl;
                }
};
class B
{
        public:
                virtual void a()
                {
                        cout<<"a() in B"<<endl;
                }
                virtual void b()
                {
                        cout<<"b() in B"<<endl;
                }
                void c()
                {
                        cout<<"c() in B"<<endl;
                }
                void d()
                {
                        cout<<"d() in B"<<endl;
                }
};
class C:public A,public B
{
        public:
                virtual void a()
                {
                        cout<<"a() in C"<<endl;
                }
                void c()
                {
                        cout<<"c() in C"<<endl;
                }
                void d()
                {
                        cout<<"d() in C"<<endl;
                }
};
int main()
{
        C c;
        //c.b();   //b()在A, B类中都定义为虚函数, C中没有无法确定使用哪个版本
        c.B::b();  //解决办法
        cout<<endl;

        A* pA = &c;
        pA->a();
        pA->b();  //b()在A, B类中都是虚函数, C类中没有定义, 编译器无法确定使用
            //哪个版本, 只能采用静态联编. 由于pA的类型是A *,所以输出: b() in A
        pA->c();  //c()在A中为虚函数, B中为普通函数, C中进行了重定义. 此时输出
            //取决于指针pA的类型A, 由于c()在A中为虚函数, 故按照虚函数的规则处理,输出c() in C
        //pA->d();  //d只在B和C中有,静态联编
        cout<<endl;

        B* pB = &c;
        pB->a();  //a()在A, B , C三个类中都是虚函数, 调用C类的c(), 输出: a() in C
        pB->b();  //b()在A, B类中都是虚函数, C类中没有定义, 编译器无法确定使用
            //哪个版本, 只能采用静态联编. 由于pB的类型是B *,所以输出: b() in B
        pB->c();  //c()在A中为虚函数, B中为普通函数, C中进行了重定义. 此时输出
            //取决于指针pB的类型B, 由于c()在B中为普通函数, 故按照普通函数的规则处理,输出c() in B
        pB->d();  //d()在B, C类中都定义为普通函数, C中的d()会隐藏基类B中的d(),
            //但pB类型为B *, 故输出d() in B
        cout<<endl;

        C* pC = &c;
        pC->a();  //a()在A, B , C三个类中都是虚函数, 调用C类的c(), 输出: a() in C
        //pC->b();  //b()在A, B类中都定义为虚函数, C中无法确定使用哪个版本,
            //引起二义性错误. 解决: pC->B::b();
        pC->c();  //c()在A中为虚函数, B中为普通函数, C中进行了重定义(?). 此时输//出取决于指针pC的类型C, c()在C中无论是虚函数还是普通函数, 都输出c() in C
        pC->d();  //d()在B, C类中都定义为普通函数, C中的d()会隐藏基类B中的d(),
            //但pC类型为C *, 故输出d() in C
        return 0;
}








posted on 2018-07-25 20:45  正在加载……  阅读(159)  评论(0编辑  收藏  举报