C++中普通函数,虚函数和纯虚函数的不同

本人对java可能比较熟悉,现在在学习C++的过程,会与Java进行对比的学习,在学习到多态的时候,对虚函数,纯虚函数和普通函数的概念不是很清楚,在查阅资料后,进行一个梳理

首先是Java中,比如类A继承自类B,类B中的方法只要不是Final修饰的,类A都可以对其进行重写,而且在调用的时候,对执行类A中重写后的方法。而C++就有所不同了。

在C++中,比如类A继承自类B,类B中的方法如果没有用virtual修饰的,那么这个方法就是普通方法,类A就不应该对其进行重写,因为即使重写后,类A中调用该方法执行的还是类B的方法。类似于被强制写死了。前提是句柄是基类

#include <iostream>
using namespace std;

class People
{
public:
	virtual void sleep() = 0; // 纯虚函数,说明该类是抽象类,不能创建对象
	virtual void say(){       //虚函数,该方法子类可以重写
		cout << "people say" << endl;
	} 
	void read(){              //普通函数,子类如果重写,那么用People做句柄,执行的依然是基类
		cout << "People read" << endl;
	}
};

class Student :public People{
public:
	void sleep(){
		cout << "Student sleep" << endl;
	}
	void say(){
		cout << "Student say" << endl;
	}

	void read(){
		cout << "Student read" << endl;
	}

};

int main()
{
	
	People *stu = new Student;
	stu->read();
	stu->say();
	stu->sleep();


	Student *stu1 = new Student;
	stu1->read();
	stu1->say();
	stu1->sleep();

	delete stu;
	delete stu1;

	return 0;



}

执行的结果可以看出来,普通函数会固定的执行基类的方法,而不是子类的方法。

还有Java中有GC机制, 所以基本上不需要用户来手动的回收内存,但是C++中却不同,在创建对象的时候,有两种方式

一种就是通过new,在java中基本上所以自己创建的类生成对象都是要用new,而C++中的new和java中的new就不同了。这点一开始很不适用。另一种方式跟java的new方式很像,只是没有new关键字。所以这里C++中就出现一个另一个函数,析构函数

而一般情况下,析构函数是虚函数,这是因为,在我们写程序过程中,经常使用多态,所以基类的析构函数不是虚函数,那么在完成内存回收的时候,会调用基类的析构函数,而不调用自类的析构函数,很容易造成内存泄漏。

C++中子类执行完析构函数,会自动的执行基类的析构函数。

  如果基本的析构函数不是虚函数,那么例子如下

     

#include <iostream>
using namespace std;

class People
{
public:
	 ~People(){
		cout << "people delete" << endl;
	}
	virtual void sleep() = 0; // 
	virtual void say(){
		cout << "people say" << endl;
	}
	void read(){
		cout << "People read" << endl;
	}
};

class Student :public People{
public:
	~Student(){
		cout << "student delete" << endl;
	}
	void sleep(){
		cout << "Student sleep" << endl;
	}
	void say(){
		cout << "Student say" << endl;
	}

	void read(){
		cout << "Student read" << endl;
	}

};

int main()
{
	
	People *stu = new Student;
	stu->read();
	stu->say();
	stu->sleep();

	cout << "----------------------------------------------" << endl;

	Student *stu1 = new Student;
	stu1->read();
	stu1->say();
	stu1->sleep();

	cout << "----------------------------------------------" << endl;
	delete stu;
	delete stu1;

	
	return 0;



}

执行结果可以看出stu没有执行子类的析构函数,只执行了基类的析构函数。

   如果将基类的析构函数变成虚函数,那么执行结果如下:

    

所以从这里知道,一般情况下,基类的析构函数是需要设置为虚函数的,而且子类执行完析构函数会自动执行基类的析构函数的。那么构造函数呢,我们再来看一下

在C++中构造函数是不能为虚函数的,因为所有的构造函数都是用来构造对象的,而虚函数是为了让通过用基类的指针,动态绑定的决定执行谁的方法。而在执行构造函数执行之前是没有对象存在的。所以也就没有任何意义。

而子类和基类的构造函数执行顺序呢?

#include <iostream>
using namespace std;

class People
{
public:
	People(){
		cout << "peopeo new" << endl;
	}

	virtual ~People(){
		cout << "people delete" << endl;
	}
	virtual void sleep() = 0; // 
	virtual void say(){
		cout << "people say" << endl;
	}
	void read(){
		cout << "People read" << endl;
	}
};

class Student :public People{
public:
	Student(){
		cout << "student new" << endl;
	}
	~Student(){
		cout << "student delete" << endl;
	}
	void sleep(){
		cout << "Student sleep" << endl;
	}
	void say(){
		cout << "Student say" << endl;
	}

	void read(){
		cout << "Student read" << endl;
	}

};

int main()
{
	
	People *stu = new Student;
	stu->read();
	stu->say();
	stu->sleep();

	cout << "----------------------------------------------" << endl;

	Student *stu1 = new Student;
	stu1->read();
	stu1->say();
	stu1->sleep();

	cout << "----------------------------------------------" << endl;
	delete stu;
	delete stu1;

	
	return 0;



}

执行的结果可以看出,在执行子类的构造函数之前会先执行基类的构造函数

以上就是C++中构造函数,析构函数,纯虚函数,虚函数和普通函数的区别。

总结:纯虚函数类似于java中抽象函数,只是在虚函数定义后加上=0,而java中是只定义即可。

          基类析构函数一般是虚函数,执行完子类的析构函数后会自动执行基类的析构函数。

         构造函数不可能是虚函数的,没有意义,执行构造函数的时候,会先执行基类的构造函数再执行子类的构造函数。

猜你喜欢

转载自blog.csdn.net/sinat_33822516/article/details/89681239