首页 > 编程语言 > 详细

c++之析构函数是否设置为虚函数

时间:2020-05-26 22:46:24      阅读:82      评论:0      收藏:0      [点我收藏+]

1.首先说一下,析构顺序

派生类--> 成员类 --> 基类

2.为什么需要把基类设置为虚析构

因为多态
在c++中,可以使用父类指针指向子类,产生多态行为

代码

#include <iostream>
class TestFather{
public:
    ~TestFather() {
        std::cout << "~TestFather()" << std::endl;
    }
};
class TestChild : public TestFather {
public:
    ~TestChild() {
        std::cout << "~TestChild()" << std::endl;
    }
};


int main() {
    TestFather* p = new TestChild();
    delete p;
}

//////////////////////////
执行结果  
~TestFather()

原因就是,你直接给编译器一个TestFather指针,delete的时候,编译器一看这不就是TestFather,直接调用TestFather析构函数
换成虚析构呢
代码

#include <iostream>
class TestFather{
public:
    virtual ~TestFather() {
        std::cout << "~TestFather()" << std::endl;
    }
};
class TestChild : public TestFather {
public:
    ~TestChild() {
        std::cout << "~TestChild()" << std::endl;
    }
};


int main() {
    TestFather* p = new TestChild();
    delete p;
}

///////
执行结果
~TestChild()
~TestFather()

正确了,在delete的时候,编译器会先看TestFather的析构函数是不是虚函数,如果是的话才会产生正常的析构顺序行为,派生类-->成员类-->基类

虚析构函数的本质

虚析构其实也就是虚函数加上析构函数,本质就是会维护一个虚表和指向虚表的指针,在上面代码中TestFather这里面的虚表就只有~TestFather()这一个函数,使用虚函数代表会增加一个指针的内存开销

默认的析构函数

当我们不定义虚构函数的时候,编译器会默认生成一个什么都不做的析构函数,但是注意了默认生成的析构函数就是普通函数不是虚函数!!!因为虚函数会带来额外开销,c++追求的是速度

纯虚构析构函数

就是纯虚函数加上析构函数,一般我们把函数设置纯虚函数都是不想这个类实例化,抽象出来的顶层父类,并且这个纯虚函数不能实现。但是在纯虚析构这里优点不同
代码

#include <iostream>
class TestFather{
public:
    virtual ~TestFather() = 0;
};
TestFather::~TestFather() {
    std::cout << "~TestFather()" << std::endl;
}

class TestChild : public TestFather {
public:
    ~TestChild() {
        std::cout << "~TestChild()" << std::endl;
    }
};


int main() {
    TestFather* p = new TestChild();
    delete p;
}

//结果和上面的相同

因为析构函数的调用顺序是派生类 成员类 基类,就算你基类是纯虚函数,编译器还是会产生对他的调用,所以要保证为纯虚析构提供函数体,如果你不做编译器会自动加上。
这里的纯虚实现要在外面实现,不能在类中 = 0之后直接实现,那样直接违反了语法

关于virtual的隐士传播

在上面的代码中我们基类设置为纯虚函数的时候,这个virtual关键字会被一直继承下去
代码

#include <iostream>
class TestFather{
public:
    virtual ~TestFather() = 0;
};
TestFather :: ~TestFather() {
    std::cout << "~TestFather()" << std::endl;
}

class TestChild : public TestFather {
public:
    ~TestChild() {
        std::cout << "~TestChild()" << std::endl;
    }
};

class TestSun : public TestChild {
public:
    ~TestSun() {
        std::cout << "~TestSun()" << std::endl;
    }
};


int main() {
    TestFather* p = new TestSun();
    delete p;
}

结果:
~TestSun()
~TestChild()
~TestFather()

所以当基类是virtual函数,无论子类的相同函数加或者不加这个关键字都是virtual的,但是为了其他人看代码方便,建议手动把从基类继承的虚函数加上virtual

总结:

明确你的类会不会被继承,当作基类使用,把类的析构函数都设置为虚函数和不设置为虚函数都是不好的
1.如果你的类会被继承,当作基类,那么一定要把基类析构函数设置为虚函数
2.如果你的类不会被继承,单纯的类,那么不需要把析构函数设置为析构函数,因为会浪费空间,多一个虚表指针

c++之析构函数是否设置为虚函数

原文:https://www.cnblogs.com/zero-waring/p/12968658.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!