经常在网上看到大家在讨论静态函数与虚函数的区别,往往可以看到统一的答案是:静态函数在编译的时候就已经确定运行时机,虚函数在运行的时候动态绑定。虚函数因为用了虚函数表机制,调用的时候会增加一次内存开销。
这个答案是正确的,但是一般不懂得虚函数表原理的人,看了可能也是一头头雾水。下面我们就先来说说什么是虚函数表:
虚函数表: 当一个类中包含被virtual 关键字修饰的成员函数时,该成员函数就成为了一个虚函数。头一个含有虚函数的类锁所实例化出来的对象都拥有同一个虚函数表,在对象中含有一个虚函数指针 *_vptr, 该指针指向该类的虚函数表,虚函数表保存的是类中虚函数的地址(一个类可能有多个虚函数)。
了解了什么是虚函数,大家可能会问:
虚函数有什么用呢?
当一个子类继承了一个含有虚函数的基类,并重写了该基类中的一个虚函数,我们就说这两个类构成多态。子类继承基类的同时,基类的虚函数表也被子类继承,不同的是被子类重写的虚函数将会替代原来虚函数表中对应的基类的虚函数的地址。从而基类与子类调用同名的虚函数时,所调用的就不是同一个函数,从而体现了多态和虚函数表的作用。
接下来我们讨论标题的问题:
静态函数与虚函数的区别?
我们知道类的静态函数是没有this指针的,调用它时不需要创建对象,通过:类名 ::函数名(参数)的形式直接调用。静态函数只有唯一的一份,因此它的地址是固定不变的, 所以编译的时候但凡遇到调用该静态函数的时候就知道调用的是哪一个函数,因此说静态函数在编译的时候就已经确定运行时机。 而虚函数则不然,看下面的代码:
class A
{
public:
virtual void fun()
{
cout<<"i am A <<endl;
}
}
class B: public A
{
public:
virtual void fun()
{
cout<<"I am B" <<endl;
}
};
int main()
{
A a ;
B b;
A* pb = &b;
pb->fun();
return 0;
}
类A与类B构成多态,创建了 A类指针pb指向 B类对象,当程序编译的时候只对语法等进行检测,该语句没有什么问题,但是编译器此时无法确定调用的是哪一个 fun() 函数,因为类A类B中都含有fun函数,因此只能是在程序运行的时候通过 pb指针 查看对象的虚函数表(访问虚函数表就是所谓的访问内存 内存)才能确定该函数的地址,即确定调用的是哪一个函数。这就解释了所说的“虚函数在运行的时候动态绑定。虚函数因为用了虚函数表机制,调用的时候会增加一次内存开销。”
以上就是我对静态函数与虚函数区别的理解。理解不对的地方希望大家指出,共同进步谢谢!!