C++编程总结之虚函数的使用

对于一个单一的类来说,析构函数是不是虚函数,其没有实质性的意义。但是当当前类作为基类的时候,基类的析构函数是不是虚函数则会对程序带来不同程度的影响。

看下下面的代码运行结果:

#include<iostream>
using namespace std;
class Base
{
public:
	Base()
	{
		cout << "Base:Constructor" <<endl;
	}
	~Base()
	{
		cout << "Base:Destructor" << endl;
	}
};

class DerivedA:public Base
{
public:
	DerivedA()
	{
		cout << "DerivedA:Constructor" <<endl;
	}
	~DerivedA()
	{
		cout << "DerivedA:Destructor" << endl;
	}
};

class DerivedB:public DerivedA
{
public:
	DerivedB()
	{
		cout << "DerivedB:Constructor" <<endl;
	}
	~DerivedB()
	{
		cout << "DerivedB:Destructor" <<endl;
	}
};

int main()
{
	Base* tmp = new DerivedA();
	delete tmp;
	return 0;
}

运行结果为:

运行结果大家估计看的出来,当析构函数为非虚函数时,delete tmp的时候,只去调用了基类的析构函数,并没有调用派生类的析构函数。

下面基类的析构函数使用需虚析构试试看结果如何:

#include<iostream>
using namespace std;
class Base
{
public:
	Base()
	{
		cout << "Base:Constructor" <<endl;
	}
	virtual ~Base()
	{
		cout << "Base:Destructor" << endl;
	}
};

class DerivedA:public Base
{
public:
	DerivedA()
	{
		cout << "DerivedA:Constructor" <<endl;
	}
	~DerivedA()
	{
		cout << "DerivedA:Destructor" << endl;
	}
};

class DerivedB:public DerivedA
{
public:
	DerivedB()
	{
		cout << "DerivedB:Constructor" <<endl;
	}
	~DerivedB()
	{
		cout << "DerivedB:Destructor" <<endl;
	}
};

int main()
{
	Base* tmp = new DerivedA();
	delete tmp;
	return 0;
}

运行结果为:

这个时候,函数调用delete tmp的时候,先调用了派生类的析构函数,然后调用了基类的析构函数。

通常情况下,一个类的析构函数中,总是去处理一些需要释放内存资源的工作,而当析构函数没有被正确调用的时候,那么可能会造成本该释放的内存在程序结束的时候不被释放,从而造成内存的泄露。当数据量大的时候可能会造成很大的损失。并且对于一个C++程序员,时刻保证程序不出现内存泄露,使我们必须时刻注意的问题。

综上所述,当我们需要把当前类作为基类使用的时候,我们必须注意析构函数虚化的处理。当然当不做基类的时候,我们可以不去设置虚析构。

时间: 2025-01-01 02:54:20

C++编程总结之虚函数的使用的相关文章

关于C++与Java中虚函数问题的读书笔记

之前一直用C++编程,对虚函数还是一些较为肤浅的理解.可近期由于某些原因搞了下Java,发现有些知识点不熟,于是站在先驱巨人的肩上谈谈C++与Java中虚函数问题. Java中的虚函数 以下是段别人的代码,输入结果竟是Base,这让一直以来用C/C++的我有些莫不着头脑,不是Java里对象是引用吗?C/C++中通过指向基类的指针或引用来指向派生类,那么对于虚函数来说通过基类指针使用的是指向的派生类.但在Java中没有keyword标明虚函数,此时就不是非常明确究竟调用的谁. class base

Hello,C++(5)纯虚函数和抽象类

纯虚函数和抽象类 下面通过一个例子来说明纯虚函数的定义方法 在这个类当中,我们定义了一个普通的虚函数,并且也定义了一个纯虚函数.那么,纯虚函数是什么呢??从上面的定义可以看到,纯虚函数就是没有函数体,同时在定义的时候,其函数名后面要加上“= 0”. 纯虚函数的实现原理 本节从虚函数表的角度来说明纯虚函数的实现原理. 上面就是我们在前面课程讲到的多态的实现原理,在讲这一部分的时候,讲到了虚函数表以及虚函数表指针.如果我们定义了Shape这样的类,那么,Shape类当中,因为有虚函数和纯虚函数,所以

C++ Primer 学习笔记_34_面向对象编程(5)--虚函数与多态(二):纯虚函数、抽象类、虚析构函数、动态创建对象

C++ Primer 学习笔记_34_面向对象编程(5)--虚函数与多态(二):纯虚函数.抽象类.虚析构函数.动态创建对象 一.纯虚函数 1.虚函数是实现多态性的前提 需要在基类中定义共同的接口 接口要定义为虚函数 2.如果基类的接口没办法实现怎么办? 如形状类Shape 解决方法 将这些接口定义为纯虚函数 3.在基类中不能给出有意义的虚函数定义,这时可以把它声明成纯虚函数,把它的定义留给派生类来做 4.定义纯虚函数: class <类名> { virtual <类型> <函

C++ Primer 学习笔记33_面向对象编程(4)--虚函数与多态(一):多态、派生类重定义、虚函数的访问、 . 和-&gt;的区别、虚析构函数、object slicing与虚函数

C++ Primer学习笔记33_面向对象编程(4)--虚函数与多态(一):多态.派生类重定义.虚函数的访问. . 和->的区别.虚析构函数.object slicing与虚函数 一.多态 多态可以简单地概括为"一个接口,多种方法",前面讲过的重载就是一种简单的多态,一个函数名(调用接口)对应着几个不同的函数原型(方法). 更通俗的说,多态行是指同一个操作作用于不同的对象就会产生不同的响应.或者说,多态性是指发出同样的消息被不同类型的对象接收时有可能导致完全不同的行为. 多态行分

C++ Primer 学习笔记_70_面向对象编程 --纯虚函数、容器与继承

面向对象编程 --纯虚函数.容器与继承 I.纯虚函数 在函数形参后面写上 =0 以指定纯虚函数: class Disc_item : public Item_base { public: double net_price(size_t) const = 0; //指定纯虚函数 }; 将函数定义为纯虚函数能够说明,该函数为后代类型提供了可以覆盖的接口,但是这个类的版本绝不会调用.重要的是,用户将不能创建Disc_item类型的对象. Disc_item discount; //Error Bulk

虚函数和模板编程的一点共性和特征模板的一个例子

最近在看元编程中,对虚函数和模板编程有一点点感悟,写一篇博客简单总结一下. 虚函数和模板是C++里面很棒的特征,他们都提供了一种方法,让程序在编译中完成一些计算,去掉的这些计算在比较low的编程方式中,是需要在程序运行中执行的.在这里,我要强调的是:"在编译过程中完成一些计算". 我会举两个例子,一个是虚函数的,比较简单,另一个例子是关于特征模板的,在例子中,根据模板参数的类型自动选择模板的底层数据结构. 第一个例子是比较简单的虚函数的例子,有很多种水果的类型,我们有一个函数要展示他们

C++ Primer 学习笔记_70_面向对象编程 -纯虚函数、器皿与继承

面向对象编程 --纯虚函数.容器与继承 I.纯虚函数 在函数形参后面写上 =0 以指定纯虚函数: class Disc_item : public Item_base { public: double net_price(size_t) const = 0; //指定纯虚函数 }; 将函数定义为纯虚函数能够说明,该函数为后代类型提供了可以覆盖的接口,但是这个类的版本绝不会调用.重要的是,用户将不能创建Disc_item类型的对象. Disc_item discount; //Error Bulk

C++ Primer 学习笔记_35_面向对象编程(6)--虚函数与多态(三):虚函数表指针(vptr)及虚基类表指针(bptr)、C++对象模型

C++ Primer 学习笔记_35_面向对象编程(6)--虚函数与多态(三):虚函数表指针(vptr)及虚基类表指针(bptr).C++对象模型 一.虚函数表指针(vptr)及虚基类表指针(bptr) C++在布局以及存取时间上主要的额外负担是由virtual引起的,包括: virtual function机制:用以支持一个有效率的"执行期绑定": virtual base class:用以实现多次在继承体系中的基类,有一个单一而被共享的实体. 1.虚函数表指针 C++中,有两种数据

《C++编程思想》 第十四章 多态和虚函数 (原书代码+习题+讲解)

一.相关知识点 函数调用捆绑 把函数体与函数调用相联系称为捆绑(binding).当捆绑在程序运行之前(由编译器和连接器)完成时,称为早捆绑.我们可能没有听到过这个术语,因为在过程语言中是不会有的:C编译只有一种函数调用,就是早捆绑.上面程序中的问题是早捆绑引起的,因为编译器在只有 instrument地址时它不知道正确的调用函数.解决方法被称为晚捆绑,这意味着捆绑在运行时发生,基于对象的类型.晚捆绑又称为动态捆绑或运行时捆绑.当一个语言实现晚捆绑时,必须有一种机制在运行时确定对象的类型和合适的