c++ 虚函数与构造函数及析构函数

虚函数与构造/析构函数注意事项

  1. 虚函数,本质上是指针,可以通过监视变量查看.
  2. 如果类中有虚函数,类大小要加4字节,一个指针大小.
  3. 类的构造函数不可以是虚函数,编译也无法通过,因为子类对象中的父类拷贝无法初始化.
  4. 使用多态继承,父类析构函数必须为虚函数,不然不会调用子类析构函数,会造成内存泄露.

虚函数,本质上是指针

#include <iostream>

using namespace std;

class MyClass
{
public:
	virtual void hello()
	{
		cout << "MyClass" << endl;
	}
};

class My1 :public MyClass
{
public:
	void hello()
	{
		cout << "My1" << endl;
	}
};

int main(int argc, char *argv[])
{
	MyClass* my = new My1;
	my->hello();
	
	cout << "MyClass size:" << sizeof(MyClass) << endl;

	delete my;
	cin.get();
	return 0;
}

在gdb中,监视my指向

在gdb中查看虚函数指针

在vs中,查看my

在vs中查看虚函数指针

如果类中有虚函数,类大小要加4字节,一个指针大小

计算类大小,如果有虚函数,要加上4个字节

类的构造函数不可以是虚函数

在vs和g++中,都无法编译通过.
在vs中编译提示:
在vs中,构造函数加上virtual关键字无法编译
在g++中编译提示:
在g++中,构造函数加上virtual关键字编译提示

多态继承,父类析构函数必须为虚函数,不然不会调用子类析构函数,会造成内存泄露

#include <iostream>

using namespace std;

class MyClass
{
public:
	char* p;
	MyClass()
	{
		cout << "父类构造" << endl;
		p = new char[1024 * 1024 * 100];
	}

	//virtual		 	 	
	~MyClass()              //如果父类析构函数,不标记为虚函数,子类析构函数不会调用,造成内存泄露
	{
		cout << "父类析构" << endl;
		delete[] p;
	}
	virtual void hello()
	{
		cout << "MyClass" << endl;
	}
};

class My1 :public MyClass
{
public:

	char *p1;
	My1()
	{
		cout << "子类构造" << endl;
		p1 = new char[1024 * 1024 * 300];
	}
	~My1()
	{
		cout << "子类析构" << endl;
		delete[] p1;
	}
	void hello()
	{
		cout << "My1" << endl;
	}
};


int main(int argc, char *argv[])
{
	MyClass* my = new My1;
	my->hello();

	cout << "MyClass size:" << sizeof(MyClass) << endl;

	delete my;
	cin.get();
	return 0;
}

查看程序内存占用:

可以看出父类和子类分配的内存情况

在释放my内存占用:

在释放子类时,只释放100兆内存

输出结果:


如果在父类的析构函数中,加上virtual,查看输出结果

只是将父类中,析构函数上方,注释virtual关键字,取消注释,得出的结果:
在父类中析构函数中,加上virtual,子类的析构函数进行了调用,内存进行了释放
秋风 2018-04-18