• 虚函数与纯虚函数


    ifndef bmw_h #define bmw_h

    class W {   public:     virtual void f(void) = 0;//纯虚函数=0

        virtual void g(void) = 0; //纯虚函数

        virtual void h(void) = 0;

        virtual void k(void);//虚函数

    };

    class MW : public virtual W {

      public:     virtual void g(void);//派生类重写函数g(void)

    };

    class BW : public virtual W {

      public:     virtual void f(void);

    };

    class BMW: public BW, public MW, public virtual W {

      public:     virtual void h(void); };

    虚函数的作用是:在基类和派生类中,若基类和派生类具有相同的函数(返回值类型不构成多态,但参数要相同),无论此时声明谁的对象(基类或派生类),基类的函数的实现都会覆盖派生类的实现,这个时候只要将基类,(或基类和派生类同时)声明为虚函数,可消除此种现象

    引入纯虚函数的意义:在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理

    在许多情况下,基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类派生类去做。这就是纯虚函数的作用。

    纯虚函数可以让类先具有一个操作名称,而没有操作内容,让派生类在继承时再去具体地给出定义。凡是含有纯虚函数的类叫做抽象类。这种类不能声明对象,只是作为基类为派生类服务。除非在派生类中完全实现基类中所有的的纯虚函数,否则,派生类也变成了抽象类,不能实例化对象。

    #include <stdio.h> #include "bmw.h"

    extern void gg();  // Defined in bmw1.c to force a second copy of the

                       // vtables for BMW to be generated. Later eliminated

                       // by armlink.

    void g(BMW *pbmw) {    

      pbmw->f();     // should be BW::f():

         pbmw->g();     // should be MW::g();

          pbmw->h();     // should be BMW::h();

          pbmw->k();     // should be W::k(); }//虚函数调用规则体现

    void h(BMW *pbmw)

    {     MW *pmw = pbmw;

        pmw->f();      // should be BW::f()... }//指针赋值之后调用规律

    BMW bmw;

    static char *bw = (char *)&bmw.__B_BW;   // This exploits the implementation

    static char *mw = (char *)&bmw.__B_MW;   // and is not portable C++...

    static char *pw = (char *)&bmw.__V_W;//指针赋值操作

    void MW::g(void) {

        printf("MW::g(), this %s mw ", (char *)this == mw ? "==" : "!="); }//类似与断言assert、==

    void BW::f(void) {

        printf("BW::f(), this %s bw ", (char *)this == bw ? "==" : "!="); }//==

    void BMW::h(void) {

        printf("BMW::h(), this %s bmw ",(char *)this == (char *)&bmw ? "==" : "!="); }//==

    void W::k(void) {     printf("W::k(), this %s pw ", (char *)this == pw ? "==" : "!="); }//==

    int main() {

        printf(" Expected output from g():

                BW::f(), this == bw

                MW::g(), this == mw  

               BMW::h(), this == bmw

                W::k(), this == pw ");

        printf("........calling g()........ ");

        g(&bmw);

        printf(" Expected output from h(): BW::f(), this == bw ");

        printf("........calling h()........ ");

        h(&bmw);  

       printf(" Expected output from gg():

                BW::f(), this != bw

                MW::g(), this != mw

                BMW::h(), this != bmw

                W::k(), this != pw ");

        printf("........calling gg()........ ");

        gg();

        return 0; }

  • 相关阅读:
    .net core 大文件分片上传
    Python 运算符
    CF1398G Running Competition FFT
    Luogu「StOI-2」简单的树 树链剖分+线段树+倍增
    LOJ#3145. 「APIO2019」桥梁 分块+可撤销并查集
    【UNR #4】序列妙妙值 分块+DP
    LuoguP5008 [yLOI2018] 锦鲤抄 tarjan+贪心
    windows提权
    基于 Laravel 框架的内容管理系统
    趣谈、浅析CRLF和LF
  • 原文地址:https://www.cnblogs.com/defen/p/4499713.html
Copyright © 2020-2023  润新知