C++的虚函数及虚指针
首先,本文的绝大部分思路来自于该博客,向博主表示感谢
先看上述文章,再看本文,估计收获更大
结论
总的来说:
1.虚函数表是针对“类”而言:
(1)当该类有虚函数时,就会生成虚函数表(一个存放虚函数指针的函数指针数组),一个虚函数表对应一个虚指针;
(2)当该类作为基类,其派生类对基类的(一个或者多个)虚函数进行重写时,派生类的虚函数表中,相应的函数指针的值就会发生变化;
2.虚指针是通过“类的对象”来体现:
(1)同一个类,创造的不同对象,其虚指针的值是一样的,全都是指向该类的虚函数表(函数指针数组的首地址?应该是了);
(2)不同的类创建的对象,无论其基类的虚函数是否被重写,其虚指针的值(与其基类创建的对象相比)是不同的;
3.对于多重继承:
经过多重继承的派生类,其含有多个虚指针(肯定啊!毕竟虚函数表是和类有直接关系的,派生类继承于多个基类,当然有多个虚函数表啦~~~也就有多个虚函数指针啦~~~),且派生类对象虚和基类对象的虚指针的值不同,无论是否进行虚函数的重写(当然啦!毕竟是不同的类生成的对象嘛~~~而且进行虚函数的重写,影响的是虚指针,这个函数指针数组中,元素的值,注意断句啊亲)。
理解了上述两大点,这第三大点也就顺理成章的理解了
下面,有图有真相,biu~biu~biu~
环境:win7+VS2012
对于1.1的解释:当该类有虚函数时,就会生成虚函数表(一个存放虚函数指针的函数指针数组)
class Base1 //有虚函数
{
public:
virtual void f1()
{
cout<<"Base1 vir_f1"<<endl;
}
virtual void f2()
{
cout<<"Base1 vir_f2"<<endl;
}
};
class Base2 //没有虚函数
{
void f3()
{
cout<<"Base2 vir_f3"<<endl;
}
void f4()
{
cout<<"Base2 vir_f4"<<endl;
}
};
int main()
{
Base1 b1; //有虚函数类的对象
Base2 b2; //没有虚函数类的对象
}
由上图可以看出,Base1类是有虚函数的,其创建的对象,有虚函数表(红色部分的下面,[0][1]分别是虚函数的函数指针);而Base2类是没有虚函数的,其创建的对象,没有虚函数表
对于1.2的解释:当该类作为基类,其派生类对基类的(一个或者多个)虚函数进行重写时,派生类的虚函数表中,相应的函数指针的值就会发生变化
class Base1 //基类,带2个虚函数
{
public:
virtual void f1()
{
cout<<"Base1 vir_f1"<<endl;
}
virtual void f2()
{
cout<<"Base1 vir_f2"<<endl;
}
};
class Deriver:public Base1 //派生类,仅重写一个基类的虚函数
{
public:
virtual void f1()
{
cout<<"Deriver vir_f1"<<endl;
}
};
int main()
{
Base1 b1;
Deriver d1;
}
由上图可以看出,基类的对象b1,派生类的对象是d1,其中,b1和d1中的第一个元素[0]的值不同,是因为派生类已经对基类的虚函数f1()进行了重写,而b1和d1中的第二个元素[1]值相同,是因为派生类没有对虚函数f2()进行重写
对于2.1的解释:同一个类,创造的不同对象,其虚指针的值是一样的,全都是指向该类的虚函数表
class Base1
{
public:
virtual void f1()
{
cout<<"Base1 vir_f1"<<endl;
}
virtual void f2()
{
cout<<"Base1 vir_f2"<<endl;
}
};
class Deriver:public Base1 //派生类重写虚函数
{
public:
virtual void f1()
{
cout<<"Deriver vir_f1"<<endl;
}
virtual void f2()
{
cout<<"Deriver vir_f2"<<endl;
}
};
int main()
{
Base1 b1,b2,b3; //基类创建多个对象
Deriver d1,d2,d3; //派生类创建多个对象
}
看,同一类,创建的所有对象,其虚函数指针的值都是相同的
对于2.2的解释:不同的类创建的对象,无论其基类的虚函数是否被重写,其虚指针的值(与其基类创建的对象相比)是不同的
(将基类的虚函数进行重写,在1.2中已完成,不再进行说明,下述派生类没有重写基类的虚函数的情况)
class Base1
{
public:
virtual void f1()
{
cout<<"Base1 vir_f1"<<endl;
}
virtual void f2()
{
cout<<"Base1 vir_f2"<<endl;
}
};
class Deriver:public Base1 //派生类没有重写虚函数
{};
int main()
{
Base1 b1;
Deriver d1;
}
看,派生类并没有对基类的虚函数进行重写,但派生类对象和基类对象的虚函数指针是不同滴~~~~
对于3的解释:
class Base1 //基类1
{
public:
virtual void f1()
{
cout<<"Base1 vir_f1"<<endl;
}
virtual void f2()
{
cout<<"Base1 vir_f2"<<endl;
}
};
class Base2 //基类2
{
virtual void f3()
{
cout<<"Base2 vir_f3"<<endl;
}
virtual void f4()
{
cout<<"Base2 vir_f4"<<endl;
}
};
class Deriver:public Base1,public Base2 //多重继承,并且把基类全部的虚函数进行了重写
{
virtual void f1()
{
cout<<"Deriver vir_f1"<<endl;
}
virtual void f2()
{
cout<<"Deriver vir_f2"<<endl;
}
virtual void f3()
{
cout<<"Deriver vir_f3"<<endl;
}
virtual void f4()
{
cout<<"Deriver vir_f4"<<endl;
}
};
int main()
{
Base1 b1;
Base2 b2;
Deriver d1;
}
看,多重继承了吧?
派生类的有两个虚指针吧?(因为派生类继承于两个基类啊)
这两个虚指针的值和基类对象的虚指针值不一样吧?(因为派生类和两个基类,分属于三个不同的类啊)
派生类中,虚指针中元素的值 和对应基类的 虚指针中 元素的值 不一样吧?(因为派生类把所有的虚函数进行了重写了啊,否则对应元素的值是相同的,毕竟指向的是同一个函数啊)