本帖最后由 鸦领主 于 2021-2-14 19:38 编辑
1.虚函数: 虚函数一定是重写函数,在基类重写函数前加virtual关键字就是虚函数
当基类里面有虚函数的时候就会生成一个四个字节的指针指向虚函数表,
不管有多少虚函数都会存在虚函数表里面所以这个类会多出4个字节。
struct Base//基类
{
void Realfunc()//实函数
{
cout << "Base:Realfunc" << endl;
}
virtual void Virtualfunc()//虚函数
{
cout << "Base:Virtualfunc" << endl;
}
};
struct Derive:Base//派生类
{
void Realfunc()//实函数
{
cout << "Realfunc:Realfunc" << endl;
}
virtual void Virtualfunc()//虚函数
{
cout << "Realfunc:Virtualfunc" << endl;
}
};
int main()
{
Base b,*pb;
Derive d;
b.Realfunc();//Base 实函数是:函数不区分谁构造的,根据当场调用者的类型执行,调用者类型是Base
b.Virtualfunc();//Base 虚函数是:函数区分谁构造的,不根据当场调用者的类型执行,b对象构造了他
d.Realfunc();//Derive 实函数是:函数不区分谁构造的,根据当场调用者的类型执行,调用者类型是Derive
d.Virtualfunc();//Derive 虚函数是:函数区分谁构造的,不根据当场调用者的类型执行,d对象构造了他
//类的对象:使用基类和派生类的对象调用重写函数,用什么对象调用就调用什么类的重写函数
pb = &d; //取d的地址
pb->Realfunc();//Base 实函数:函数不区分谁构造的,根据当场调用者的类型执行,调用者类型是Base
pb->Virtualfunc();//Derive 虚函数:b1对象构造了他,但是b1指向的地址是d的地址,相当于是d构造了他,不会根据b1的类型执行
pb = &b;
pb->Realfunc();//Base:
pb->Virtualfunc();//Base:
//基类指针:当调用普通重写函数时,是什么类指针调用就执行什么类重写函数,
//当调用虚拟函数时,指针指向的是哪个类的对象的地址,就调用哪个类的重写函数
//引用是指针同理
Base &b1 = b;
b1.Realfunc();//Base:
b1.Virtualfunc();//Base:
Base &b2 = d;
b2.Realfunc();//Base:
b2.Virtualfunc();//Derive:
}
//基类引用变量:当调用普通重写函数时,调用基类的普通重写函数,
//当调用虚拟函数时,引用的是哪个类的对象,就调用哪个类的重写函数。
c++ 虚函数
静态动态绑定
//动态绑定:运行时绑定,通过地址实现(根据虚表)
void TestbyRet(Base &Ret)
{
b.Realfunc;
b.Virtualfunc;
}
//静态绑定:编译时绑定,通过对象调用(对象的类型)
void TestbyRet(Base Ret)//重新建立基类的对象
{
b.Realfunc;
b.Virtualfunc;
}
纯虚函数
只是一个形式,再基类里面不做任何行动,纯粹的是一个摆设,都是为派生类准备的
列如:
再基类里面什么都不做就可以写成这样
4、纯虚函数:
a)概念:纯虚函数是一种特殊的虚函数,在许多情况下,在基类中不能对虚函数给出有意义的实现,
而把它声明为纯虚函数,它的实现留给该基类的派生类去做。这就是纯虚函数的作用。
定叉: virtual<类型><函数名>(参数表)=0;
普通函数必须有函数体,而纯虚函数使用一个=0的标志代替了普通虚函数的函数体;
c每个纯虚函数都必须在派生类中实列化
(新建栈内或堆内对象时,纯虚函数的错误提示:”不能实例化“
第一种可能是因为派生类没有提供足够的基类纯虚函数的重写函数。
第二种可能是因为使用基类来构建对象
|