类中的虚函数与普通成员函数在对象上调用的区别,及对构造函数和析构函数小的理解

由简单的代码出发,边看边分析:

第一个例子:
#include <iostream> 
using namespace std;
class A
{
public:
	A( )
	{
		cout << "constructor" << endl ;
	} 
	~A( ) {
		cout << "destructor" << endl;
	}
	
	void printA( ) {
		cout << "print A" << endl;
	}
	virtual void  printB( ) {
		cout << "print B" << endl;
	}
};
class B { 
public:
	 B(){cout<<"constructor B"<<endl;
	 };       
	 ~B(){cout<<"destructor B"<<endl;
	 }
};
int main( ) {
	A a ;   //在栈区
	B b;       //作用:看空类占用的内存,以及看是否会自动调用c的析构函数。
	A *c = new(&a)A;  //这一句是在a的位置(栈区)重新实例化A的一个对象c。
	//虽然在栈区,但main()函数结束时(其他函数也同理),栈区释放内存时,在栈区释放这块内存调用的是a的析构函数。
	//不会析构c,虽然用delete c ;会自动调用c的析构函数并释放那块内存,但不能用delete c ;会触发异常。
	//可以最后显式调用c的析构函数 c->~A();告诉编译器,析构了c。
	A *d=new A;

	cout << sizeof(a )<<"\t"<< sizeof( b ) << endl;
	(&a)->printA( );   
	(&a)->printB( );
	c->printA( );
	c->printB( );
	cout<<endl;
	d->printB( );//如果这句放到delete d;后面,会触发异常。
	delete d;    //如果删了,那输出结果中的printB后面那句destructor将不会打印出来,
	//因为在运行期间,这块内存一直被占用,没被回收。程序运行结束,也没打印。系统回收进程所有占用的资源(包括内存)在进程结束之后。
    d->printA( );//即使放到delete d;后面,  也能正常运行。可以看第二个例子。
	
}

以上代码能正常运行,运行结果:

constructor   //a
constructor B  //b
constructor    //c
constructor    //d
4       1   //空类B的对象 默认占用1个字节,类A的实例a中第一个数据为一个指向虚函数表的指针__vfptr,所以a占用4个字节。
print A
printB
print A
printB

printB
destructor// d  在堆区,所以要用delete 释放那块内存。如果删了delete d;这句没有。
print A       //destructor B 前面没有 c 的 destructor。
destructor B  //b   先构造的后析构,可以看出,没有调用c的析构函数,但是不能通过用delete c;这句
 //调用c的析构函数,因为同时也把a的内存释放了,main()函数结束时,栈区释放不存在的a的内存时会触发异常。
 //可以最后显式调用比如 c->~A();
destructor //a   这是运行即将结束,系统释放栈区的a 占用的那块内存时,调用的析构函数,系统回收
//内存时告诉编译器这块内存,被我回收了。栈区实例化的对象内存的回收机制和普通变量差不多,
//只不过会调用下析构函数,即使析构函数是空的。

第二个例子:

把main()中的 A a ;替换为 A *a=NULL;

int main( ) {
	A *a=NULL ;
	cout << sizeof( *a )<<endl;
	a->printA( );   
	a->printB( );
}

输出结果:

4 
print A
//下面进入异常,不会打印print B

printA()函数,因为在代码区,在a->printA( ); 这句中能调用成功。
构造函数没调用,到虚函数printB()那显示异常;
析构函数也没调用;
虚函数是由对象内第一个数据(一个指向虚函数表的指针__vfptr)指向虚函数表,由于NULL内不能写数据。当对象没有构造时,没有数据,也就是没有指向虚函数表的指针__vfptr,关于这点可参考
C++虚函数表,虚表指针,内存分布

这个博主写的比较透彻,受益匪浅。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值