c++ primer 类中函数调用过程解析(虚函数与作用域) P550疑问解析

本文详细解析C++ Primer第五版中关于类中函数调用的过程,特别是针对P550页的疑问。首先,确定对象的静态类型,然后在该类型中查找函数。如果找不到,将搜索基类,直至找到或到达基类顶端。对于虚函数,调用版本由对象的动态类型决定。通过示例代码解释为何在特定情况下会调用基类的虚函数版本,以及未覆盖虚函数时的行为。
摘要由CSDN通过智能技术生成

函数调用过程

即c++ primer 第五版中P549所谈,这里强调几点。
假定是p->mem() 或者obj.mem()

  • 首先确定静态类型,即p的类型。
  • 然后在这个静态类型中名字查找函数,即查找有没有mem。即 名字查找
  • 若没有则去静态类型(即p的类型)的直接基类中找,仍没有继续向基类中找。直到基类顶端。仍没有的话,就返回查找失败,发生错误。
  • 若找到了,接着类型检查,如果类型匹配就看这个函数是否是虚函数
  • 若类型不匹配,则直接返回类型匹配错误因为编译器名字查找,只要查到了,就停止名字查找了。
  • 若是虚函数,并且用指针或者引用调用,那么调用这个虚函数的哪个版本,依据是对象的动态类型
  • 否则,就常规调用,即用静态类型来调用。

P550疑问

主要对P550的bp2->fcn();bp2->f2();有疑问。可以看如下代码:

class Base{
friend class Pal;
public:
    virtual int fcn(){ std::cout << "基类的虚函数" << std::endl; return 1; }
private:
    char priv_mem;
protected:
    int prot_mem;
};

class D1 :public Base{
public:
    int fcn(int a){ std::cout << "D1类的有参数的fcn" << std::endl; return a; }
    virtual void f2(){ std::cout << "D1类的虚函数f2()" << std::endl; };//新的虚函数
};

class D2 :public D1{
public:
    int fcn(int a){ std::cout << "D2类的有参数的fcn" << std::endl; return a; };
    int fcn(){ std::cout << "D2类的无参数的fcn" << std::endl; return 1; };
    void f2(){ std::cout << "D2的f2()" << std::endl; };
};

int main(int argc, const char *argv[])
{
    Base bobj; D1 d1obj; D2 d2obj;
    Base *bp1 = &bobj, *bp2 = &d1obj, *bp3 = &d2obj;
    bp1->fcn();
    bp2->fcn();
    bp3->fcn();
    //bp2->f2(); //错误 Base没有名为f2的成员
    system("pause");
    return 0;
}

1.首先解释bp2->fcn()为什么调用的是基类的那个虚函数。
根据函数调用规则,先在静态类型即Base类中找fcn,名字查找,找到了。接着进行类型检查,确实是无参类型,再看是否是虚函数,是的,那么依据动态类型来调用。动态类型是D1类,即调用D1::fcn();。但是D1类没有覆盖fcn()虚函数,是直接继承的,故调用的仍是Base::fcn()

2.再看bp2->f2();依然先名字查找,静态类型为Base,没有f2,故报错Base类无成员f2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值