1. 定义及作用
1. 基类和派生类
通过继承机制,可以利用已有的数据类型来定义新的数据类型。所定义的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员。称已存在的用来派生新类的类为基类,又称为父类;称由基类派生出的新类为派生类,又称子类。
2. 虚函数
在基类中用virtual声明成员函数为虚函数,在派生类中重新定义此函数,改变此函数的功能。在C++中虚函数可以继承:当一个成员函数被声明为虚函数时,其派生类的同名函数都会自动成为虚函数,如果派生类没有覆盖基类的虚函数,则在调用时调用基类的函数定义。
在类的继承层次结构中的不同层次可以出现名字、参数个数和类型都相同而功能不同的函数。编译器按照先子类后父类的顺序进行查找覆盖,当子类中有父类相同原型的成员函数时,要想调用父类的成员函数,需要对父类重新引用调用。虚函数可以解决子类和父类相同原型成员函数的函数调用问题。 虚函数允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类的同名函数。
【重载和覆盖的区别】:
重载:在同一层次函数名相同;
覆盖:在继承层次中成员函数的函数原型完全相同。
3. 静态函数
在函数的返回类型前面加上static关键字,函数就被定义为静态函数。详细可见static关键字的作用
4. 析构函数
析构函数是面向对象编程中的一个概念,是一种特殊的成员函数,它没有参数,不返回任何值,也没有返回类型,用于在对象生命周期结束时执行清理工作和资源释放操作,在对象销毁时自动被调用,避免内存泄漏和资源泄露的问题。
在C++中,析构函数的名称与类名相同,但要在类名钱面加上一个位取反符~。
如果用户没有编写析构函数,编译系统会自动生成一个缺省的析构函数,即使定义了,系统也还是会生成,在调用时会先调用用户定义的析构函数,再调用系统生成的。
如果一个类中有指针,且在使用过程中动态地申请了内存,那么最好显示构造析构函数在销毁类之前,释放掉申请的内存空间,避免内存泄漏。
类析构顺序:
派生类本身的析构函数→对象成员的析构函数→基类的析构函数
#include<iostream>
using namespace std;
class Myclass{
public:
//构造函数
Myclass(){
cout<<"调用构造函数"<<endl;
}
//析构函数
~Myclass(){
cout<<"调用析构函数"<<endl;
}
};
int main(){
Myclass obj;// 创建对象
//在main函数结束时,对象obj将销毁,析构函数会被自动调用
return ;
}
2. 为什么析构函数必须是虚函数?
将可能会被继承的父类的析构函数设置为虚函数,可以保证当我们new一个子类时,使用基类指针指向这个子类对象时,释放基类指针时可以释放掉子类的空间,防止内存泄漏。
3. 为什么C++默认的析构函数不是虚函数?
C++默认的析构函数不是虚函数的原因是虚函数需要额外的虚函数表和虚表指针,占用额外的内存。而对于不会被继承的类来说,其析构函数如果是虚函数,就会浪费内存,因此C++默认的析构函数不是虚函数,而是只有当需要当作父类时,设置为虚函数。
4. 虚函数、静态函数两者区别
静态函数在编译时就已经确定运行时机,虚函数在运行期间动态绑定。虚函数因为用了虚函数表机制,调用的时候会增加一次内存开销。