C++ 友元 绑定

1. 纯虚函数和虚函数都能定义为另一个类的成员友元;由于纯虚函数一般不定义函数体,故一般不会访问另一个类的成员,定义为其他类的友元意义不大;
2. 一个函数是一个基类的友元,该函数不会自动成为这个基类的派生类的友元;
3.编译程序为有虚函数 类创建一个虚函数入口地址表VFT,表首地址存放在对象的起始单元中;当对象调用虚函数时,通过其起始单元得到VFT首址,晚期绑定到相应的函数成员。对象类型不同则绑定的函数不同,从而表现出和对象类型相适应的多态特征;
4. 定义纯虚函数是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数
示例代码
#include <iostream>

using namespace std;
class A{
    virtual void c()
    {
        cout << "Construct A" << endl;
    }
    virtual void d()
    {
        cout << "Deconstruct A" << endl;
    }
    virtual void e(){}
    public:
    A() { c(); };
    virtual ~A(){ d(); }
};
class B:A
{
    virtual void c()
    {
        cout << "Construct B" << endl;
    }
    virtual void d()
    {
        cout << "Deconstruct B" << endl;
    }
    public:
    B(){c();}//等价于B( ):A( ){c( );}
    virtual ~B() { d();}//virtual可省
};
int main()
{
    B b; //先构造的后析构:像栈
    return 0;
}
运行结果
Construct A
Construct B
Deconstruct B
Deconstruct A
说明
基类A和派生类B都有虚函数,对应的虚函数入口地址表分别为VFTA,VFTB,派生列对象b在各阶段;
  • 构造:先将VFTA首地址存放在b的起始单元,在A类构造函数的函数体执行时,A类对象调用的虚函数与VFTA绑定,执行的虚函数将是A类的函数,在B类构造函数体执行之前,将VFTB,首地址存放在b的其实单元,绑定和执行的将是B类的函数。如果B类没有定义这样额函数,根据面向对象的作用域,将调用基类A的相同原型函数;
  • 生存:b的起始单元指向VFTB,绑定和执行的将是B类的函数,如果B类没有定义这样的函数,根据面向对象的作用域,将调用基类A的相同原型的函数;
  • 析构:b的起始单元指向VFTB,绑定和执行的方式相同,在b的析构函数执行完后基类的析构函数执行前,将VFTA首址存放在b地址的起始单元,伺候绑定和执行的将是A的函数;如果A类没有定义这样的函数,根据面向对象的作用域,将调用基类A的相同原型的函数。
  • 上述代码的内存图
    在这里插入图片描述
类的存储空间
派生类对象的字节数仅计算基类和派生类的非静态数据成员。当基类或派生类包含虚函数或纯虚函数时,派生类对象的存储空间还包括虚函数入口地址表首址所占的存储单元。
  • 如果基类定义了虚函数或者纯虚函数,则派生类对
    象将其起始单元作为共享单元,用于存放基类和派
    生类的虚函数入口地址表首址。
  • 如果基类没有定义虚函数,而派生类定义了虚函数,
    则派生类的存储空间由三个部分组成:
    • 基类存储空间,
    • 派生类虚函数入口地址表首址,
    • 该派生类新定义的数据成员。
发布了52 篇原创文章 · 获赞 15 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/jzj_c_love/article/details/102749284
今日推荐