首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

关于基类析构函数的有关问题

2013-08-14 
关于基类析构函数的问题有这么几个问题:1.基类析构函数不为虚的话,用派生类指针转化为基类指针之后,删除这

关于基类析构函数的问题
有这么几个问题:
1.基类析构函数不为虚的话,用派生类指针转化为基类指针之后,删除这个基类指针时,调用的都只是基类的析构函数,是这样吗?
2.如果真的是这样,那我bear *a = new panda;delete a的时候,输出的是:
animal init...
bear init...
panda init...
bear delete...
animal delete...
为甚么animal的析构也调用了?然后是不是可以说,1的说法不是和严谨?有没有一种更严谨的说法?
3.一般情况下,是不是应该把父类的析构函数都设为虚的?比如我这个例子,除了把animal的析构设为虚之外,也应该把bear的析构设为虚?
4.我废话是不是太多了?还是说我的思维太严谨了关于基类析构函数的有关问题


#include <iostream>

class animal
{
public:
    animal()
    {
        std::cout<<"animal init..."<<std::endl;
    }
    //virtual
    ~animal()
    {
        std::cout<<"animal delete..."<<std::endl;
    }
};

class bear : public animal
{
public:
    bear()
    {
        std::cout<<"bear init..."<<std::endl;
    }

    //virtual
    ~bear()
    {
        std::cout<<"bear delete..."<<std::endl;
    }
};

class panda : public bear
{
public:
    panda()
    {
        std::cout<<"panda init..."<<std::endl;
    }
    ~panda()
    {
        std::cout<<"panda delete..."<<std::endl;
    }
    
};


int main()
{
    bear *a = new panda;
    //animal *a = new panda;
    delete a;
}
析构函数 基类 指针
------解决方案--------------------


可以看《深入解析C++对象模型》这本书,说的很详细

用基类指针指向派生类的对象时,指针是通过要读取的内容去判断的,所以他只保留了基类的部分,通过这个指针是无法访问派生类的部分的

在delete的时候,因为基类里面有定义的析构函数,如果派生类中没有定义析构函数,会调用基类的析构函数。即使当派生类中定义了析构函数,C++也会默认把基类的析构函数添加进派生类中已定义的析构函数的。
[解决办法]
一个类析构时,不管它的基类虚函数是不是virtual的,都是先析构自身再析构基类。这和构造时先构造基类再构造自身的顺序相反。
所以
bear *a = new panda;
delete a;
会输出
animal init...
bear init...
panda init...
bear delete...
animal delete...
如果animal的析构函数是virtual的,就会有动态绑定。输出结果是:
animal init...
bear init...
panda init...
panda delete...
bear delete...
animal delete...
还有虚函数的基本知识:
只要基类函数是virtual的,派生类相应函数不管有没有virtual修饰都是vritual的.
[解决办法]

引用:
可以看《深入解析C++对象模型》这本书,说的很详细

用基类指针指向派生类的对象时,指针是通过要读取的内容去判断的,所以他只保留了基类的部分,通过这个指针是无法访问派生类的部分的

在delete的时候,因为基类里面有定义的析构函数,如果派生类中没有定义析构函数,会调用基类的析构函数。即使当派生类中定义了析构函数,C++也会默认把基类的析构函数添加进派生类中已定义的析构函数的。


2.如果真的是这样,那我bear *a = new panda;delete a的时候,输出的是:
-------------------------------------
bear指针,当然调用bear的析构函数(因为bear的析构不是虚函数),然后再调用bear的基类animal的析构,但是,panda并没有析构。所以这个对象没有完整的析构,不正确。
派生类的析构,自己析构完成一定是会调用他的基类析构的。这和虚函数没关系,虚不虚都要这样一层层往上析构。

3.一般情况下,是不是应该把父类的析构函数都设为虚的?比如我这个例子,除了把animal的析构设为虚之外,也应该把bear的析构设为虚?
--------------------------------------------------
如果要用多态的特性,基类的虚函数必须要虚的,否则析构对象不完整。
不用多态的特性,则不需要虚函数,毕竟虚函数多了个查表的过程,影响些效率。
只要基类某个函数是虚的,所有继承这个基类的函数(包括继承的继承)都是虚的,不写virtual,系统默认也是virtual的
一日为虚,终身为虚。
[解决办法]
引用:
有这么几个问题:
1.基类析构函数不为虚的话,用派生类指针转化为基类指针之后,删除这个基类指针时,调用的都只是基类的析构函数,是这样吗?

调用的只是基类的析构函数其实应为:不会调用子类的析构函数。 


A* p =...
detele p; //A及其基类的析构是会被调用,*p的动态类型的析构函数不会被调用

前提:析构函数非虚

热点排行