• 纯虚函数与虚函数


     虚函数
    虚函数



    http://zh.wikipedia.org/zh/%E8%99%9A%E5%87%BD%E6%95%B0_%28%E7%A8%8B%E5%BA%8F%E8%AF%AD%E8%A8%80%29
    这里面有代码解释,很清晰易懂,
    BCDEF类继承自(A),
    BCDEF的构造函数各不相同,若是声明为virtual。 
    我们New  一个A类,用子类的构造函数来构造,
    那么A类调用了 子类的构造函数,
    (若这个函数,没有声明为virtual,则一直调用的是A类的方法)


    上面的构造函数,可以也是其他的方法。





    虚函数是面向对象程序设计中的一个重要的概念。当从父类中继承的时候,虚函数和被继承的函数具有相同的签名(有相同的虚函数表)。

    但是在运行过程中,运行系统将根据对象的型別,自动地选择适当的具体实现运行。(运行时多态)

    虚函数是面向对象编程实现多型的基本手段。


    虚函数在设计模式方面扮演重要角色。例如,《设计模式》一书中提到的23种设计模式中,仅5个对象创建模式就有4个用到了虚函数(抽象工厂、工厂方法、生成器、原型),只有singleton没有用到。




    例子
    STDMETHOD(Load)(const BSTR bstrFilePath);  //虚函数

    PURE STDMETHOD(Load)(const BSTR bstrFilePath); //纯虚函数,  

    objbase.h  中的定义,



    #if defined(__cplusplus) && !defined(CINTERFACE)
    //#define interface               struct FAR
    #define __STRUCT__ struct
    #define interface __STRUCT__
    #define STDMETHOD(method)       virtual HRESULT STDMETHODCALLTYPE method
    #define STDMETHOD_(type,method) virtual type STDMETHODCALLTYPE method
    #define STDMETHODV(method)       virtual HRESULT STDMETHODVCALLTYPE method
    #define STDMETHODV_(type,method) virtual type STDMETHODVCALLTYPE method
    #define PURE                    = 0            //windows API中常常会这样写 method() = 0;  这个=0 也就意味着PURE,首地址为NULL,当然无法创建实例对象
    #define THIS_
    #define THIS                    void
    #define DECLARE_INTERFACE(iface)    interface DECLSPEC_NOVTABLE iface
    #define DECLARE_INTERFACE_(iface, baseiface)    interface DECLSPEC_NOVTABLE iface : public baseiface
    ====================

    class A
    {
    public:
        A()
        {
            //cout << "A()"<<endl;
        };
    
         ~A()//virtual 加上才不会内存泄漏
        {
            //cout << "~A()" << endl;
        };
    
    };
    
    
    //如果没有继承,
    class B :public A
    {
    public:
        int a1, a2, a3, a4;//  16/4= 4
        //std::string s1, s2, s3, s4;//112/4 = 28 每个string 默认大小,string 容器可以不断增大
        B()
        {
            cout << "B()" << endl;
        };
    
        ~B()
        {
            cout << "~B()" << endl;
        };
    };
    
    int main()
    {
        //引发内存泄漏, A(), B(), ~A(), 所以父类要加上虚函数 virtual ~A() , 这样就建立了虚函数表,  可以析构B
    
        while(true){
            A* p = new B();
            delete p;
        }
    }

    1.如果 父类析构 不加virtual

       B* p = new B();
       delete p;

     不会引发内存泄漏, 流程: A(), B(), ~B(), ~A()

    2.如果 父类析构 加virtual

       A* p = new B();
       delete p;
      不会引发内存泄漏, 流程: A(), B(), ~B(), ~A()

    3.如果 父类析构 不加virtual

       A* p = new B();
       delete p;
      会引发内存泄漏, 流程: A(), B(),  ~A()

    遇到一个很有趣的问题,Class B 中只有int 并不会产生 内存泄漏,  但是有string 就会发生内存泄漏,   一定是编译器 做了优化!

    ---------------------------

    class B 的 父类 不是 virtual析构, Sizeof(B)=4 bytes

    class B 的 父类 是 virtual析构,  需要再加上虚函数表,  Sizeof(B)=8 bytes

  • 相关阅读:
    T-Pot平台Honeytrap蜜罐TCP/UDP服务攻击探测及实现自动化邮件告警
    Linux判断文件是否为空,不为空则打印该文件的大小
    Linux好用的工具命令
    T-Pot平台cowrie蜜罐暴力破解探测及实现自动化邮件告警
    python工具
    python文件的基础操作
    python实现合并两个文件并打印输出
    python打开文件的N种姿势
    python工具
    python列表中元素插入位置总结
  • 原文地址:https://www.cnblogs.com/scotth/p/3163485.html
Copyright © 2020-2023  润新知