纯虚函数与虚函数
虚函数
虚函数
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