虚函数用法和注意事项总结

       通常,编译器处理虚函数的方法是:给每个对象添加一个隐藏成员。隐藏函数中保存了一个指向函数地址数组的指针,这个地址数组是虚函数表,虚函数表中保存了类中声明的虚函数的地址。

       无论类中包含的虚函数是一个还是10个,都只在对象中添加一个指针,只是指向的地址表的大小不同而已。基类中会有一个指针指向一个虚函数表,派生类中也包含一个指针。

       1,若派生类,没有重新定义虚函数,则派生类的地址表将包含基类虚函数表的内容。

       2,若提供了虚函数的重新定义,则派生类的虚函数表将保存新的地址内容。

       3,若派生类添加了新的虚函数,则新的函数地址内容将添加到派生类的虚函数表中。

       虚函数表是用数组实现的,调用虚函数时,程序查看对象中指针指向的虚函数表地址,如果调用类声明中的第n个虚函数,则使用虚函数表----地址数组中的第n个元素。

       使用虚函数增加了内存和速度成本,

        1,每个对象都增大,曾大量为一个指针的大小

        2,对每个类,编译器都创建一个虚函数表(数组实现)

        3,每次虚函数调用,都要去表中查找地址

 

       虚函数要点

      1,在基类方法的声明中使用virtual关键字可使该方法在基类、子类以及子子类中都是虚函数

      2,如果使用指向对象的引用和指针来调用虚方法,程序将根据指向的对象类型来调用,若是调用非虚方法,则根据指针或者引用的类型来调用方法

      3,如果定义的类要用作基类,则要将在派生类中重新定义的方法声明为虚拟的。

 

      一些注意点:

      1,构造函数 

      构造函数不能是虚函数,因为派生类对象建立时调用的是自己的构造函数,并不是基类的构造函数,然后在派生类的构造函数中使用父类的构造函数,这不是继承,派生类并没有继承父类的构造函数,将构造函数声明为虚拟的是没有意义的。

      2,析构函数

      析构函数必须定义为virtual的派生类中继承了父类的内容,如果父类指针指向一个子类对象,当执行析构函数时,如果析构函数不是虚拟的,则调用父类的析构函数,子类新增的内容却无法释放。如果将析构函数定义为虚拟的,则先调用子类析构函数释放内容,再调用父类析构函数释放父类内容。

     3,友元函数

     友元函数不能是虚函数,因为它不是类成员,只有成员才能使虚函数

     4,没有重新定义

     如果派生类没有重新定义,则使用基本版本

     5,重新定义隐藏方法

     假设创建了以下代码

class base
 {
public:virtual void fun(int a);
};
class derive:public base
{
public:virtual void fun();
 
};


新定义的fun()为一个不接受任何参数的函数,重新定义不会生成函数个两个重载版本,而是隐藏了基类中接受一个参数的版本,简而言之,重新定义继承的方法并不是重载,如果在派生类中重新定义函数,而不是使用相同的函数特性来覆盖基类声明,则是隐藏同名的基类方法

     所以有两条经验

a 如果要重新定义继承的方法,应确保与原来的原型完全相同 但是如果返回类型是基类指针或引用,则可以修改为指向派生类的引用和指针,这种特性是返回类型协变,因为允许返回类型随类型的变化而变化

class base
{
public:virtual base & fun(int a);
};
 
class derive:public base
{
public:virtual derive & fun(int a);
 
};


b 如果基类声明被重载了,则应该在派生类中重新定义所有的版本。

class base
{
public:virtual void fun(int a);
          virtual void fun(double x);
          virtual base & fun();
};
 
class derive:public base
{
public:virtual void fun(int a);
          virtual void fun(double x);
          virtual derive & fun();
 
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值