小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

虛析構(gòu)函數(shù)的使用(轉(zhuǎn)載?。?/span>

 quandsu 2013-08-22

一、當(dāng)你的類準(zhǔn)備給別人繼承時要提供虛析構(gòu)函數(shù)
考慮下面例子:
class A
{
public:
A(){cout << "In A constructor" << endl;}
~A(){cout << "In A destructor" << endl;}
};

class B : public A
{
public:
B()
{
 cout << "In B constructor" << endl;
m_p = new char[10];
}
~B()
{
cout << "In B destructor" << endl;
if (m_p) delete [] m_p;
}

private:
char *m_p;
};

int main(int argc, char* argv[])
{
//printf("Hello World!/n");
A *p = new B;
delete p;
return 0;
}
輸出結(jié)果:
In A constructor
In B constructor
In A destructor

并沒有調(diào)用B的析構(gòu)函數(shù),new出來的內(nèi)存沒有及時回收造成內(nèi)存泄漏。
要解決這個問題,只要將A的析構(gòu)函數(shù)定義為虛函數(shù):~A(){cout << "In A destructor" << endl;}。為什么定義為虛函數(shù)就能解決呢?我是這樣理解的:
象其它虛構(gòu)函數(shù)一樣,~B()重定義(overridden)了~A(),這樣指向派生類的指針就能根據(jù)運行時的狀態(tài)調(diào)用B的析構(gòu)函數(shù)了。這里又有一個問題:為什么還會調(diào)用A的析構(gòu)函數(shù)呢?我只能理解為析構(gòu)函數(shù)是一個特殊的函數(shù),由系統(tǒng)維護(hù)其機制。就像B.~A()是錯誤而B.~B()(雖然邏輯上不對,但語法上是正確的,編譯運行完全沒問題)是正確的一樣。

 

     

虛函數(shù)和普通成員函數(shù)的區(qū)別,是虛函數(shù)放在虛函數(shù)表中,通過對象的this指針找到該類的虛函數(shù)表,然后調(diào)用。C++即采用此機制實現(xiàn)多態(tài)。如果是普通函數(shù),每個函數(shù)的地址是死的。所以用A類的對象調(diào)用析構(gòu)函數(shù)時只能調(diào)到A的析構(gòu)。如果是虛函數(shù),則會通過指針找到B的析構(gòu)函數(shù),而B繼承自A,還會調(diào)用A的析構(gòu)函數(shù)。

因此,虛析構(gòu)函數(shù)用在有虛函數(shù)的繼承。否則,你那樣的用法也是不正確的。A *p=new B 如果沒有虛函數(shù),會導(dǎo)致截斷。

二、

////////////////////////////////////////////////////////////////////////////////
#if CODE1
#include <iostream>
//給出一個沒有虛擬析構(gòu)函數(shù)的基類
class Base
{
public:
        Base()
        {
                std::cout<<"Base::Base()"<<std::endl;
        }
        ~Base()
        {
                std::cout<<"Base::~Base()"<<std::endl;
        }
};
//給出一個沒有虛擬析構(gòu)函數(shù)的繼承類
class
 Derived:public Base
{
public:
        Derived()
        {
                std::cout<<"Derived::Derived()"<<std::endl;
        }
        ~Derived()
        {
                std::cout<<"Derived::~Derived()"<<std::endl;
        }
};
//下面的測試代碼
int
 main()
{
        {
//堆棧變量的情況
                std::cout << "----------[Derived d;]----------" << std::endl;
                Derived d;
        }
        {
//堆內(nèi)存分配,并且刪除派生類對象指針的情況
                std::cout << "----------[Derived *pd = new Derived();]----------" << std::endl;
                Derived *pd = new Derived();
                std::cout << "----------[delete pd;]----------" << std::endl;
                delete pd;
//這里會調(diào)用派生類和基類的析構(gòu)函數(shù),雖然派生類和基類的析構(gòu)函數(shù)不是虛擬的
        }
        {
//堆內(nèi)存分配,并且刪除基類對象指針的情況
                std::cout << "----------[Base *pb = new Derived();]----------" << std::endl;
                Base *pb = new Derived();
                std::cout << "----------[delete pb;]----------" << std::endl;
                delete pb;
//這里就不會調(diào)用派生類的析構(gòu)函數(shù)
        }
        return 0;
}
////////////////////////////////////////////////////////////////////////////////
//運行結(jié)果如下所示:
/*******************************************************************************
----------[Derived d;]----------
Base::Base()
Derived::Derived()
Derived::~Derived()
Base::~Base()
----------[Derived *pd = new Derived();]----------
Base::Base()
Derived::Derived()
----------[delete pd;]----------
Derived::~Derived()
Base::~Base()
----------[Base *pb = new Derived();]----------
Base::Base()
Derived::Derived()
----------[delete pb;]----------
Base::~Base()
*******************************************************************************/
////////////////////////////////////////////////////////////////////////////////
#if 0
    從上面的討論中可以看出,只有最后一種情況才會對析構(gòu)函數(shù)是否是虛擬的有要求,在
后面的討論中將會只討論這種情況。
#endif
#endif//CODE1
#if CODE2
#include <iostream>
//給出一個沒有虛擬析構(gòu)函數(shù)的基類
class
 Base
{
public:
        Base()
        {
                std::cout<<"Base::Base()"<<std::endl;
        }
        ~Base()
        {
                std::cout<<"Base::~Base()"<<std::endl;
        }
};
//給出一個有虛擬析構(gòu)函數(shù)的繼承類
class
 Derived:public Base
{
public:
        Derived()
        {
                std::cout<<"Derived::Derived()"<<std::endl;
        }
        virtual~Derived()
        {
                std::cout<<"Derived::virtual~Derived()"<<std::endl;
        }
};
//下面的測試代碼
int
 main()
{
        
//堆內(nèi)存分配,并且刪除基類對象指針的情況
        std::cout << "----------[Base *pb = new Derived();]----------" << std::endl;
        Base *pb = new Derived();
        std::cout << "----------[delete pb;]----------" << std::endl;
        delete pb;
//這里就不會調(diào)用派生類的析構(gòu)函數(shù)
        return 0;
}
////////////////////////////////////////////////////////////////////////////////
//運行結(jié)果如下所示:
/*******************************************************************************
----------[Base *pb = new Derived();]----------
Base::Base()
Derived::Derived()
----------[delete pb;]----------
Base::~Base()
*******************************************************************************/
////////////////////////////////////////////////////////////////////////////////
#if 0
    很明顯并沒有調(diào)用派生類的虛擬析構(gòu)函數(shù)。
#endif
#endif//CODE2
#if CODE3
#include <iostream>
//給出一個有虛擬析構(gòu)函數(shù)的基類
class
 Base
{
public:
        Base()
        {
                std::cout<<"Base::Base()"<<std::endl;
        }
        virtual~Base()
        {
                std::cout<<"Base::virtual~Base()"<<std::endl;
        }
};
//給出一個沒有虛擬析構(gòu)函數(shù)的繼承類
class
 Derived:public Base
{
public:
        Derived()
        {
                std::cout<<"Derived::Derived()"<<std::endl;
        }
        ~Derived()
        {
                std::cout<<"Derived::~Derived()"<<std::endl;
        }
};
//下面的測試代碼
int
 main()
{
        
//堆內(nèi)存分配,并且刪除基類對象指針的情況
        std::cout << "----------[Base *pb = new Derived();]----------" << std::endl;
        Base *pb = new Derived();
        std::cout << "----------[delete pb;]----------" << std::endl;
        delete pb;
//這里會調(diào)用派生類的析構(gòu)函數(shù)
        return 0;
}
////////////////////////////////////////////////////////////////////////////////
//運行結(jié)果如下所示:
/*******************************************************************************
----------[Base *pb = new Derived();]----------
Base::Base()
Derived::Derived()
----------[delete pb;]----------
Derived::~Derived()
Base::virtual~Base()
*******************************************************************************/
////////////////////////////////////////////////////////////////////////////////
#if 0
    很明顯調(diào)用派生類的虛擬析構(gòu)函數(shù)。但是這里值得注意的是:派生類的析構(gòu)函數(shù)并不
是虛擬的,為了說明派生類的虛擬析構(gòu)函數(shù)是否一定要是虛擬的,還需要更多的測試。
#endif
#endif//CODE3
#if CODE4
#include <iostream>
//給出一個有虛擬析構(gòu)函數(shù)的基類
class
 Base
{
public:
        Base()
        {
                std::cout<<"Base::Base()"<<std::endl;
        }
        virtual~Base()
        {
                std::cout<<"Base::virtual~Base()"<<std::endl;
        }
};
//給出一個有虛擬析構(gòu)函數(shù)的繼承類
class
 Derived:public Base
{
public:
        Derived()
        {
                std::cout<<"Derived::Derived()"<<std::endl;
        }
        virtual~Derived()
        {
                std::cout<<"Derived::virtual~Derived()"<<std::endl;
        }
};
//下面的測試代碼
int
 main()
{
        
//堆內(nèi)存分配,并且刪除基類對象指針的情況
        std::cout << "----------[Base *pb = new Derived();]----------" << std::endl;
        Base *pb = new Derived();
        std::cout << "----------[delete pb;]----------" << std::endl;
        delete pb;
//這里會調(diào)用派生類的析構(gòu)函數(shù)
        return 0;
}
////////////////////////////////////////////////////////////////////////////////
//運行結(jié)果如下所示:
/*******************************************************************************
----------[Base *pb = new Derived();]----------
Base::Base()
Derived::Derived()
----------[delete pb;]----------
Derived::virtual~Derived()
Base::virtual~Base()
*******************************************************************************/
////////////////////////////////////////////////////////////////////////////////
#if 0
    很明顯調(diào)用派生類的虛擬析構(gòu)函數(shù)。通過CODE3和CODE4可以看出只要基類的析構(gòu)函數(shù)
是虛擬的則派生類的析構(gòu)函數(shù)不論是否是虛擬的都將在刪除基類指針的時候調(diào)用派生類的
析構(gòu)函數(shù)。不過CODE3和CODE4僅僅討論的是一次一重繼承的情況。對于多次多重繼承的情
況則需要另外的單獨討論。還是先討論多次繼承的情況,然后再討論多重繼承的情況,最
后討論多次多重繼承的情況。
#endif
#endif//CODE4
#if CODE5
//測試多次繼承的情況
#include <iostream>
//給出一個有虛擬析構(gòu)函數(shù)的基類
class
 Base
{
public:
        Base()
        {
                std::cout<<"Base::Base()"<<std::endl;
        }
        virtual~Base()
        {
                std::cout<<"Base::virtual~Base()"<<std::endl;
        }
};
//給出一個沒有虛擬析構(gòu)函數(shù)的繼承類
class
 Derived1:public Base
{
public:
        Derived1()
        {
                std::cout<<"Derived1::Derived1()"<<std::endl;
        }
        ~Derived1()
        {
                std::cout<<"Derived1::~Derived1()"<<std::endl;
        }
};
//給出另一個沒有虛擬析構(gòu)函數(shù)的繼承類
class
 Derived2:public Derived1
{
public:
        Derived2()
        {
                std::cout<<"Derived2::Derived2()"<<std::endl;
        }
        ~Derived2()
        {
                std::cout<<"Derived2::~Derived2()"<<std::endl;
        }
};
//下面的測試代碼
int
 main()
{
        
//堆內(nèi)存分配,并且刪除基類對象指針的情況
        {
                std::cout << "----------[Base *pb = new Derived2();]----------" << std::endl;
                Base *pb = new Derived2();
                std::cout << "----------[delete pb;]----------" << std::endl;
                delete pb;
//這里會調(diào)用派生類的析構(gòu)函數(shù)
        }
        {
                std::cout << "----------[Base *pd1 = new Derived1();]----------" << std::endl;
                Derived1 *pd1 = new Derived2();
                std::cout << "----------[delete pd1;]----------" << std::endl;
                delete pd1;
//這里會調(diào)用派生類的析構(gòu)函數(shù)
        }
        return 0;
}
////////////////////////////////////////////////////////////////////////////////
//運行結(jié)果如下所示:
/*******************************************************************************
----------[Base *pb = new Derived2();]----------
Base::Base()
Derived1::Derived1()
Derived2::Derived2()
----------[delete pb;]----------
Derived2::~Derived2()
Derived1::~Derived1()
Base::virtual~Base()
----------[Base *pd1 = new Derived1();]----------
Base::Base()
Derived1::Derived1()
Derived2::Derived2()
----------[delete pd1;]----------
Derived2::~Derived2()
Derived1::~Derived1()
Base::virtual~Base()
*******************************************************************************/
////////////////////////////////////////////////////////////////////////////////
#if 0
    很明顯調(diào)用了所有派生類的虛擬析構(gòu)函數(shù)。但是這里值得注意的是:派生類的析構(gòu)函
數(shù)并不是虛擬的??梢钥闯鲋灰谢惖奈鰳?gòu)函數(shù)是虛擬的,那么所有的派生類不管是否
明確的寫了虛擬析構(gòu)函數(shù),派生了的析構(gòu)函數(shù)一定是虛擬的。
#endif
#endif//CODE5
#if CODE6
//測試多重繼承的情況
#include <iostream>
//給出一個有虛擬析構(gòu)函數(shù)的基類
class
 Base1
{
public:
        Base1()
        {
                std::cout<<"Base1::Base1()"<<std::endl;
        }
        virtual~Base1()
        {
                std::cout<<"Base1::virtual~Base1()"<<std::endl;
        }
};
class Base2
{
public:
        Base2()
        {
                std::cout<<"Base2::Base2()"<<std::endl;
        }
        virtual~Base2()
        {
                std::cout<<"Base2::virtual~Base2()"<<std::endl;
        }
};
//給出一個沒有虛擬析構(gòu)函數(shù)的繼承類
class
 Derived:public Base1,public Base2
{
public:
        Derived()
        {
                std::cout<<"Derived::Derived()"<<std::endl;
        }
        ~Derived()
        {
                std::cout<<"Derived::~Derived()"<<std::endl;
        }
};
//下面的測試代碼
int
 main()
{
        
//堆內(nèi)存分配,并且刪除基類對象指針的情況
        {
                std::cout << "----------[Base *pb = new Derived();]----------" << std::endl;
                Base1 *pb = new Derived();
                std::cout << "----------[delete pb;]----------" << std::endl;
                delete pb;
//這里會調(diào)用派生類的析構(gòu)函數(shù)
        }
        {
                std::cout << "----------[Base *pb = new Derived();]----------" << std::endl;
                Base2 *pb = new Derived();
                std::cout << "----------[delete pb;]----------" << std::endl;
                delete pb;
//這里會調(diào)用派生類的析構(gòu)函數(shù)
        }
        return 0;
}
////////////////////////////////////////////////////////////////////////////////
//運行結(jié)果如下所示:
/*******************************************************************************
----------[Base *pb = new Derived();]----------
Base1::Base1()
Base2::Base2()
Derived::Derived()
----------[delete pb;]----------
Derived::~Derived()
Base2::virtual~Base2()
Base1::virtual~Base1()
----------[Base *pb = new Derived();]----------
Base1::Base1()
Base2::Base2()
Derived::Derived()
----------[delete pb;]----------
Derived::~Derived()
Base2::virtual~Base2()
Base1::virtual~Base1()
*******************************************************************************/
////////////////////////////////////////////////////////////////////////////////
#if 0
    很明顯調(diào)用了所有派生類的析構(gòu)函數(shù)和基類的析構(gòu)函數(shù)。另外還可以看出只要有了多重
繼承的任意一個基類的指針都可以通過這個指針將整個對象刪除。另外還需要考慮一下某個
基類的析構(gòu)函數(shù)不是虛擬的情況。
#endif
#endif//CODE6
#if CODE7
//測試多重繼承的情況
#include <iostream>
//給出一個有虛擬析構(gòu)函數(shù)的基類
class
 Base1
{
public:
        Base1()
        {
                std::cout<<"Base1::Base1()"<<std::endl;
        }
        virtual~Base1()
        {
                std::cout<<"Base1::virtual~Base1()"<<std::endl;
        }
};
class Base2
{
public:
        Base2()
        {
                std::cout<<"Base2::Base2()"<<std::endl;
        }
        ~Base2()
        {
                std::cout<<"Base2::~Base2()"<<std::endl;
        }
};
//給出一個沒有虛擬析構(gòu)函數(shù)的繼承類
class
 Derived:public Base1,public Base2
{
public:
        Derived()
        {
                std::cout<<"Derived::Derived()"<<std::endl;
        }
        ~Derived()
        {
                std::cout<<"Derived::~Derived()"<<std::endl;
        }
};
//下面的測試代碼
int
 main()
{
        
//堆內(nèi)存分配,并且刪除基類對象指針的情況
        {
                std::cout << "----------[Base *pb = new Derived();]----------" << std::endl;
                Base1 *pb = new Derived();
                std::cout << "----------[delete pb;]----------" << std::endl;
                delete pb;
//這里會調(diào)用派生類的析構(gòu)函數(shù)
        }
        {
                std::cout << "----------[Base *pb = new Derived();]----------" << std::endl;
                Base2 *pb = new Derived();
                std::cout << "----------[delete pb;]----------" << std::endl;
                delete pb;
//這里不會調(diào)用派生類的析構(gòu)函數(shù)
        }
        return 0;
}
////////////////////////////////////////////////////////////////////////////////
//運行結(jié)果如下所示:
/*******************************************************************************
----------[Base *pb = new Derived();]----------
Base1::Base1()
Base2::Base2()
Derived::Derived()
----------[delete pb;]----------
Derived::~Derived()
Base2::~Base2()
Base1::virtual~Base1()
----------[Base *pb = new Derived();]----------
Base1::Base1()
Base2::Base2()
Derived::Derived()
----------[delete pb;]----------
Base2::~Base2()
*******************************************************************************/
////////////////////////////////////////////////////////////////////////////////
#if 0
    很明顯,是否調(diào)用所有派生類的析構(gòu)函數(shù)和基類的析構(gòu)函數(shù),取決于刪除的基類指針的
基類的析構(gòu)函數(shù)是否是虛擬的,如果指針的析構(gòu)函數(shù)是虛擬的,那么將會調(diào)用所有的派生類
的析構(gòu)函數(shù)和所有的其它基類的析構(gòu)函數(shù),否則就會象上面的第二種情況一樣僅僅刪除了基
類自身而已,導(dǎo)致對象沒有完全釋放。
#endif
#endif//CODE7

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多