虚函数理解

  • Post author:
  • Post category:其他



目录


什么是虚函数?


虚函数作用


虚函数的工作原理


虚函数实例:


什么函数不能声明为虚函数?


什么是虚函数?

指向基类的指针在操作它的多态对象时,可以根据指向的不同类对象调用其相应的函数,这个函数就是虚函数。

虚函数作用

定义了虚函数后,可以在派生类中对虚函数进行重新定义,并且可以通过基类指针或引用,在程序的运行阶段动态的选择调用基类和不同派生类中的同名函数。(如果在派生类中没有对虚函数重新定义,则它继承其基类的虚函数)

虚函数的工作原理

编译器处理虚函数的方法:给每一个对象添加一个隐藏成员。隐藏成员中保存了一个指向函数地址数组的指针。这种数组称为虚函数表。虚函数表中存储了为类对象进行声明的虚函数地址。例如,基类对象包含一个指针指向基类中所有虚函数的地址表。派生类对象将包含一个指针指向独立地址表,如果派生类提供了虚函数的新定义,该虚函数表将保存新函数的地址,如无将保存函数原始版本的地址。

总之,使用虚函数时,在内存和执行速度方面有一定的成本:

  • 每个对象都将增大,增大量为存储地址的空间;
  • 对于每个类,编译器都创建一个虚函数地址表
  • 对于每个函数调用,都需要执行一项额外的操作,即到表中查找地址。

虚函数实例:

class Base
{
public:
	virtual void Print()
	{
        print("this is class Base!\n");
    }
};

class Derived1 :public Base
{
public:
	void Print()
	{
        print("this is class Derived1!\n");
    }
};

class Derived2 :public Base
{
public:
	void Print()
	{
        print("this is class Derived2!\n");
    }
};

int main()
{
	Base Cbase;
    Derived1 child1;
    Derived2 child2;
    Cbase.Print();
    child1.Print();
    child2.Print();

    cour<<"---------"<<endl;
    Base *p1 = &Cbase;
    Base *p2 = &child1;
    Base *p3 = &child2;

    p1->Print();
    p2->Print();
    p3->Print();
    
}


/*
this is class Base!
this is class Derived1!
this is class Derived2!
--------------
this is class Base!
this is class Derived1!
this is class Derived2!
*/

什么函数不能声明为虚函数?

  • 普通函数(非成员函数)

非成员函数只能被重载overload,不能被覆盖override,声明为虚函数也没有什么意思

  • 静态成员函数

静态成员函数对于每一个类来说只有一份代码,所有的对象都共享这一份代码,没有必要动态绑定

  • 内联成员函数

inline函数在编译时被展开,虚函数在运行时才能动态绑定函数

  • 构造函数

构造函数是为了明确初始化对象成员才产生的,然而virtual function主要是为了再不完全了解细节的情况下也能正确处理对象。另外virtual函数是在不同类型的对象产生不同德动作,前提是有对象。

  • 友元函数

c++不支持友元函数的继承,没有继承特性的函数没有虚函数的说法



版权声明:本文为super8ayan原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。