300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 基类的析构函数不能被继承。_为什么要把C++类中的析构函数声明为虚函数?

基类的析构函数不能被继承。_为什么要把C++类中的析构函数声明为虚函数?

时间:2021-11-14 04:40:01

相关推荐

基类的析构函数不能被继承。_为什么要把C++类中的析构函数声明为虚函数?

如题,当一个类为基类的时候,通常其析构函数被声明为虚函数,这是为啥?

class BaseCls

{

public:

BaseCls() { printf("BaseCls()n"); }

~BaseCls() { printf("~BaseCls()n"); }

void test_func() { printf("Base::test_func()n"); }

};

class SubCls : public BaseCls

{

public:

SubCls() { printf("SubCls()n"); }

~SubCls() { printf("~SubCls()n"); }

void test_func() { printf("SubCls::test_func()n");

};

int main(void)

{

BaseCls *base = new SubCls;

base->test_func();

delete base;

return 0;

}

编译运行:

在main()函数中,定义了BaseCls类型指针,根据赋值兼容性原则,该指针可以指向动态生成子类SubCls对象的地址,此时动态生成的SubCls对象已经被充当基类使用,因为BaseCls中的test_func()函数是普通函数(并非虚函数)不能发生多态,所以打印的是基类的”Base::test_func()n”。

代码”delete base;”我们希望用来释放SubCls的空间,即调用SubCls的析构函数,释放完毕后BaseCls的析构函数。然而编译器只是根据指针类型是BaseCls而只是调用BaseCls的析构函数,SubCls的析构函数得不到调用,若在SubCls构造函数中动态分配的空间,在析构函数释放空间,那么这样就造成内存泄漏了。

如何改进?让基类BaseCls的析构函数声明为虚函数,使其在delete base时发生多态即可:

class BaseCls

{

public:

//...

virtual ~BaseCls()

{

printf("~BaseCls()n");

}

//...

};

编译运行:

将构造函数中声明为virtual后,编译器就不会简单的只根据base指针的类型而决定调用对象的构造函数,而是依据指针base所指向的实际对象而调用其构造函数,这不就是多态吗?

最后,再补充两个问题?

(1) 析构函数可以被声明为虚函数,那构造函数可以声明为虚函数吗?

- 答案是不可以。因为虚函数的调用依靠于虚函数表。然而在构造函数执行完毕后,虚函数表指针才被正确初始化。

(2) 构造函数不可以被声明为虚函数,那么构造函数的实现体中,可以实现多态吗?

- 答案还是不可以。因为析构函数一旦被调用,虚函数表指针就会销毁了。那么同理,在构造函数中实现体中也不可能发生多态行为,因为在构造函数执行时,虚函数表指针还没被正确初始化。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。