当前位置: 首页 > news >正文

做响应式网站费用/网站推广广告

做响应式网站费用,网站推广广告,单页设计用什么软件,东莞市天气1、单继承对象模型 1.1、单一继承在C编译器的内部类可以理解为结构体子类是由父类成员叠加子类新成员得到的。class Derived : public Demo{int mk;};/************************* 继承对象模型初探 ********************/#include <iostream>using namespace std;clas…

1、单继承对象模型

    1.1、单一继承

    在C++编译器的内部类可以理解为结构体
    子类是由父类成员叠加子类新成员得到的。
    class  Derived : public  Demo
    {
            int  mk;
    };
                 

/************************* 继承对象模型初探 ********************/
#include <iostream>
using namespace std;
class Demo
{
protected:
    int mi;
    int mj;
public:
    
    //虚函数
    virtual void print()
    {
        cout << "mi = " << mi << ", "
             << "mj = " << mj << endl;
    }
};
class Derived : public Demo
{
    int mk;
public:
    Derived(int i, int j, int k)
    {
     //说明那个虚函数的指针在这里,要对齐。
        mi = i;
        mj = j;
        mk = k;
    }
    
    void print()
    {
        cout << "mi = " << mi << ", "
             << "mj = " << mj << ", "
             << "mk = " << mk << endl;
    }
};
struct Test
{
    void* p;    //说明那个虚函数的指针在这里,要对齐。
    int mi;
    int mj;
    int mk;
};
int main()
{
    cout << "sizeof(Demo)" << sizeof(Demo) << endl;//12, 不是8,因为插入了一个虚函数表指针(指针长度4字节)
    cout << "sizeof(Derived)" << sizeof(Derived) << endl;//16,不是12,因为继承了父类,原因同上。
    
    Derived d(1, 2, 3);
    Test* p = reinterpret_cast<Test*>(&d);//指针之间的转换,
    
    cout << endl;
    
    //以下实验证明带有虚函数的Derived的内存模型与Test结构体是一致的!!!!!
    //1,大小相同,2。第1个成员变量vptr(虚函数)指针;3。往后依次为mi,mj,mk
    cout << "Before Change..." << endl;
    d.print();
    
    p->mi = 10;
    p->mj = 20;     //通过内存地址直接访问类里面的变量。
    p->mk = 30;
    
    cout << "After Change..." << endl;                                    
    d.print();
    return 0;
}

2、C++多态的实现原理

    2.1、当类中声明虚函数时,编译器会在类中生成一个虚函数表
    2.2、虚函数表是一个存储成员函数地址的数据结构
    2.3、虚函数表是由编译器自动生成与维护的
    2.4、virtual成员函数会被编译器放入虚函数表中
    2.5、存在虚函数时,每个对象中都有一个指向虚函数表的指针

    多态的本质分析::用C写面向对象,实现多态

#ifndef _51_2_H_
#define _51_2_H_
typedef void Demo;
typedef void Derived;
//父类
Demo* Demo_Create(int i, int j);
int Demo_GetI(Demo* pThis);
int Demo_GetJ(Demo* pThis);
int Demo_Add(Demo* pThis, int value);
void Demo_Free(Demo* pThis);
//子类
Derived* Derived_Create(int i, int j, int k); //子类的构造函数。
int Derived_GetK(Derived* pThis);
int Derived_Add(Derived* pThis, int value);
#endif

#include "51-2.h"
#include <malloc.h>
#include <stdio.h>
//利用C语言来实现面向对象..实现多态的效果。

//static 修饰函数,说明函数只能被本文件所使用。和修饰全局变量一样,限定在本文件作用域,隐藏的虚函数表。
static int Demo_Virtual_Add(Demo* pThis, int value);
static int Derived_Virtual_Add(Derived* pThis, int value);

struct VTable       //2.定义虚函数表数据结构
{//这是一张表
    int (*pAdd)(void*, int);    //3.虚函数表里面存储的内容是(函数指针),,主要这个pAdd具体指向谁,是地址层面的具体数值。
};

struct ClassDemo //父类结构体
{
    struct VTable* vptr;    //1.数定义虚函表指针 ==》 虚函数表指针的类型???
    int mi;
    int mj;
};

struct ClassDerived//子类结构体,拥有父类结构体里面的成员。也包括那个虚函数表指针
{
    struct ClassDemo d;     //模拟继承,实质就是父类成员叠加到子类成员中去。
    int mk;
};

//父类的虚函数表,static隐藏到当前文件中。//给虚函数表初始化
static struct VTable g_Demo_vtbl =  //g_Demo_vtbl的类型为static struct VTable
{
    Demo_Virtual_Add //内部都是一个函数指针,函数名。
};

//子类的虚函数表
static struct VTable g_Derived_vtbl =   //静态结构体变量。
{
    Derived_Virtual_Add//内部都是一个函数指针
};
/******************     父类    ***********************/
Demo* Demo_Create(int i, int j) //相当于构造函数
{
    struct ClassDemo* ret = (struct ClassDemo*)malloc(sizeof(struct ClassDemo));

    if(ret != 0)
    {
        //4、、只要有父类的对象产生,那么调用构造函数,关联虚函数表。
        ret->vptr = &g_Demo_vtbl;//4、、(g_Demo_vtbl)结构体类型,关联对象和虚函数表
        ret ->mi = i;
        ret ->mj = j;
    }

    return ret;
}
int Demo_GetI(Demo* pThis)
{
    struct ClassDemo* obj = (struct ClassDemo*)pThis;
    return obj->mi;
}
int Demo_GetJ(Demo* pThis)
{
    struct ClassDemo* obj = (struct ClassDemo*)pThis;
    return obj->mj;
}
//6.定义虚函数表中指针所指向的具体函数
static int Demo_Virtual_Add(Demo* pThis, int value)
{
    struct ClassDemo* obj = (struct ClassDemo*)pThis;

    return obj->mi + obj->mj + value;
}

//5.分析具体的虚函数
int Demo_Add(Demo* pThis, int value)    //是个虚函数
{
    struct ClassDemo* obj = (struct ClassDemo*)pThis;

    //从虚函数表中找到真正的实现函数
    return obj->vptr->pAdd(pThis, value);    //虚函数表具体的指向,这个vptr在对象的构造函数中初始化。
}

void Demo_Free(Demo* pThis)
{
    free(pThis);
}

/******************         Derived类  ,子类      ***********************/
Derived* Derived_Create(int i, int j, int k)    //构造函数
{
    struct ClassDerived* ret = (struct ClassDerived*)malloc(sizeof(struct ClassDerived));
    if(ret != NULL)
    {
         //只要有子类的对象产生,那么调用构造函数,关联虚函数
         //(g_Derived_vtbl)结构体类型,关联对象和虚函数表
        ret -> d.vptr = &g_Derived_vtbl;   //结构体指针,可以访问结构体成员。
        ret -> d.mi = i;
        ret -> d.mj = j;
        ret -> mk = k;
    }
    return ret;
}
int Derived_GetK(Derived* pThis)
{
    struct ClassDerived* obj = (struct ClassDerived*)pThis;

    return obj->mk;
}

//定义子类虚函数表中指针所指向的具体函数
static int Derived_Virtual_Add(Derived* pThis, int value)
{
    struct ClassDerived* obj = (struct ClassDerived*)pThis;

    return obj->mk + value;
}

//分析虚函数
int Derived_Add(Derived* pThis, int value)
{
    struct ClassDerived* obj = (struct ClassDerived*)pThis;

    //从虚函数表中找到真正的实现函数
    return obj->d.vptr->pAdd(pThis, value);
}


#include <stdio.h>
#include "51-2.h"
void run(Demo* p, int v)
{
    int r = Demo_Add(p, v); //多态
    printf("r = %d\n", r);
}
int main()
{    //这两个指针类型都是void的。
    Demo* pb = Demo_Create(1, 2);
    Derived* pd = Derived_Create(1, 22, 333);
    
    printf("pb->add(3) = %d\n", Demo_Add(pb, 3));
    printf("pd->add(3) = %d\n", Derived_Add(pd, 3));
    
    run(pb, 3);
    run(pd, 3);
    
    Demo_Free(pb);
    Demo_Free(pd);
    return 0;
}

C语言实现多态的思路

5、小结

    5.1、继承的本质是父子间成员变量的叠加
    5.2、C++中的多态是通过虚函数表实现
    5.3、虚函数表是由编译器自动生成与维护的
    5.4、虚函数的调用效率低于普通成员函数。(虚函数要经过几次寻址)

        【参考资料】:C++对象模型之详述C++对象的内存布局

 课程中通过 void* 指针保证具体的结构体成员是不能在外界被访问的, 以 此模拟 C++ 中 private protected。 因此,在头文件中定义了如下的语句:

typedef void Demo;
typedef void Derived; 

Demo 和 Derived 的本质依旧是 void, 所以,用 Demo* 指针和 Derived* 指针 指向具体的对象时,无法访问对象中的成员变量, 这样就达到了“外界无法访问类
中私有成员” 的封装效果! 继承的本质是父类成员与子类成员的叠加,所以在用 C 语言写面向对象程 序的时候, 可以直接考虑结构体成员的叠加即可。课程中的实现直接将 struct ClassDemo d 作为 struct ClassDerived 的第一个成员, 以此表现两个自定义数
据类型间的继承关系。 因为 struct ClassDerived 变量的实际内存分布就是由
struct ClassDemo 的成员以及 struct ClassDerived 中新定义的成员组成的, 这 样就直接实现了继承的本质, 所以说 struct ClassDerived 继承自 struct ClassDemo。 下一步要实现的就是多态了! 多态在 C++ 中的实现本质是通过虚函数表完
成的 而虚函数表是编译器自主产生和维护的数据结构。因此,接下来要解决的问 题就是如何在 C 语言中自定义虚函数表?课程中认为通过结构体变量模拟 C++ 中的虚函数表是比较理想的一种选择,所以有了下面的代码:

struct VTable
{
int (*pAdd)(void*, int);
};

必须要注意的是,课程中由于复制粘贴的缘故,误将 pAdd 指针的类型定义成了
int (*)(Derived*, int) , 这从 C 语言的角度算不上错误,因为 Derived* 的本质就 void* , 所以编译运行都没有问题。但是,从面向对象的角度,这里可以说是 一种语义上的错误! 因为 pAdd 必须可以指向父类中定义的 Add 函数版本,也可 以指向子类中定义的 Add 函数版本,所以说用 Derived* 作为第一个参数表示实 际对象并不合适,应该直接使用 void* 。 有了类型后就可以定义实际的虚函数表了, 在 C 语言中用具有文件作用域
的全局变量表示实际的虚函数表是最合适的,因此有了下面的代码:

// 父类对象使用的虚函数表
static struct VTable g_Demo_vtbl =
{
Demo_Virtual_Add
};

// 子类对象使用的虚函数表
static struct VTable g_Derived_vtbl =
{
Derived_Virtual_Add
};
每个对象中都拥有一个指向虚函数表的指针,而所有父类对象都指向 g_Demo_vtbl,所以所有子类对象都指向 g_Derived_vtbl。当一切就绪后,实际 调用虚函数的过程就是通过虚函数表中的对应指针来完成的。





































































































http://www.jmfq.cn/news/4813687.html

相关文章:

  • 武汉做胃镜国医堂z网站/百度地图导航2022最新版下载
  • 做服装最好的网站建设/天津搜狗seo推广
  • 广州网站建设 .超凡科技/旅游seo整站优化
  • 平板上做网站的软件/win7优化大师好不好
  • wordpress 3.6下载/如何优化seo关键词
  • 亲姐弟做愛电影在线网站/天津百度搜索网站排名
  • 国产 做 视频网站/app排名优化
  • 购物分享网站怎么做盈利/网络营销产品的首选产品
  • 高中生自己做网站/广州网络推广外包平台
  • 优良的定制网站建设/seo零基础培训
  • 虚拟机怎么做多个网站/凡科建站官网
  • 如何为一个网站做短连接/广州百度关键词排名
  • 建设网站的意义 作用是什么意思/“跨年”等关键词搜索达年内峰值
  • 网站建设交印花税吗/网站的营销推广
  • 网站建设案例展示/广州专门做网站
  • 毕业论文做网站/百度推广登录入口下载
  • 微信小游戏开发平台/灰色词优化培训
  • 学校响应式网站模板/关键词排名优化公司哪家强
  • 响应式设计 手机网站/seo博客
  • 做网站能用的字体/电商平台怎么搭建
  • 大良营销网站建设好么/seo服务如何收费
  • 商务网站开发工具不包括/神马快速排名优化工具
  • 做鞋子出口需要作网站吗/年度关键词有哪些
  • 网站建设捌金手指下拉六/如何建立电商平台
  • 有网站怎么做app/域名注册腾讯云
  • wordpress商城微信支付/seo推广效果怎么样
  • 五合一网站建设方案/凡科建站下载
  • 网站开发和设计人员的岗位要求/广告联盟app
  • 青岛圭谷网站建设公司/公司网络推广排名定制
  • 做招聘网站需要什么资质/企业网站注册域名的步骤