纯虚函数与虚函数

 虚函数
虚函数



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

 

posted @ 2013-06-30 12:31  scott_h  阅读(1213)  评论(0编辑  收藏  举报