虚函数和多态

一、虚函数

  • 在类的定义中,前面有 virtual 关键字的成员函数称为虚函数;
  • virtual 关键字只用在类定义里的函数声明中,写函数体时不用。
  • class Base 
    {
        virtual int Fun() ; // 虚函数
    };
    
    int Base::Fun() // virtual 字段不用在函数体时定义
    { }

二、多态的表现形式

派生类的指针(对象) 可以赋给 基类指针(引用);

通过基类指针(引用)调用基类和派生类中的同名虚函数时:

1.若该指针(引用)指向一个基类的对象,那么被调用的是基类的虚函数;

2.若该指针(引用)指向一个派生类的对象,那么被调用的是派生类的虚函数。

这种机制就叫做多态,即调用哪个虚函数,取决于指针(引用)指向哪种类型的对象

// 基类
class CFather 
{
public:
    virtual void Fun() { } // 虚函数
};

// 派生类
class CSon : public CFather 
{ 
public :
    virtual void Fun() { }
};

int main() 
{
    CSon son;
    CFather *p = &son;
    p->Fun(); //调用哪个虚函数取决于 p 指向哪种类型的对象
    //引用形式:
    //CFather &r = son;
    //r.Fun();
    return 0;
}

作者:小林coding
链接:https://zhuanlan.zhihu.com/p/104605966
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

上例子中的 p(r) 指针(引用)指向的是 CSon 类对象,所以 p->Fun() (r.Fun())调用的是 CSon 类里的 Fun 成员函数。

三、多态作用

在面向对象的程序设计中使用“多态”,能够增强程序的可扩展性,即程序需要修改或增加功能时,需要改动和增加的代码较少。

四、多态在函数中的体现

1.在非构造函数、非析构函数的成员函数中调用 虚函数 ,是多态

下面的代码,pBase->fun1()输出结果是什么呢?

class Base 
{
public:
    void fun1() 
    { 
        fun2(); 
    }
    
    virtual void fun2()  // 虚函数
    { 
        cout << "Base::fun2()" << endl; 
    }
};

class Derived : public Base 
{
public:
    virtual void fun2()  // 虚函数
    { 
        cout << "Derived:fun2()" << endl; 
    }
};

int main() 
{
    Derived d;
    Base * pBase = & d;
    pBase->fun1();
    return 0;
}

pBase 指针对象虽然指向的是派生类对象,但是派生类里没有 fun1 成员函数,则就调用基类的 fun1 成员函数,Base::fun1() 里又会调用基类的 fun2 成员函数,所以输出结果是Base::fun2()

这时修改下代码

class Base 
{
public:
    void fun1() 
    { 
        this->fun2();  // this是基类指针,fun2是虚函数,所以是多态
    }
}

this 指针的作用就是指向成员函数所作用的对象,所以非静态成员函数中可以直接使用this来代表指向该函数作用的对象的指针。

pBase指针对象指向的是派生类对象,派生类中没有fun1成员函数,所以就会调用基类的fun1的成员函数,在Base::fun1()成员函数体里执行this->fun2()时,实际上指向的是派生类对象fun2成员函数。

所以正确的输出结果是:Derived:fun2()

2.在构造函数和析构函数中调用 虚函数,不是多态。编译时即可确定,调用的函数是自己的类或基类中定义的函数,不会等到运行时才决定调用自己的还是派生类的函数。

例子

// 基类
class CFather 
{
public:
    virtual void hello() // 虚函数
    {
        cout<<"hello from father"<<endl; 
    }
    
    virtual void bye() // 虚函数
    {
        cout<<"bye from father"<<endl; 
    }
};

// 派生类
class CSon : public CFather
{ 
public:
    CSon() // 构造函数
    { 
        hello(); 
    }
    
    ~CSon()  // 析构函数
    { 
        bye();
    }

    virtual void hello() // 虚函数
    { 
        cout<<"hello from son"<<endl;
    }
};

int main()
{
    CSon son;
    CFather *pfather;
    pfather = & son;
    pfather->hello(); //多态
    return 0;
}

输出结果

hello from son  // 构造son对象时执行的构造函数
hello from son  // 多态
bye from father // son对象析构时,由于CSon类没有bye成员函数,所以调用了基类的bye成员函数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值