针对博客里面的问题随便说几句,其实COM我没怎么用过
http://www.cnblogs.com/mumuliang/archive/2011/01/14/1935792.html
对于疑问1:假设不用纯虚类,类的使用者可以new来创建其实例。那么如果有一天IFastString的开发者突然觉得这个类的实现加一个私有成员变量会更加高效。然后灾难就来了,IFastString这个类的大小变了,于是所有的使用IFastString的人都需要重新编译他的代码。想象一下,windows有一点点的升级,都要重新编译所有的应用程序是多么的可怕。
对于疑问2:出于疑问1的考虑,COM必然选择纯虚类作为接口。类的使用者不知道类的实现,所以无法创建类的实例(没法new). 于是COM实现了一种create by name的机制,把类的创建交给了类的实现者。既然类的创建是一个函数CoCreateInstance而不是直接调用new和构造函数,那么摧毁这个类的时候也就不应该调用析构函数,析构函数的调用者自然应该是构造函数的调用者。假设是类的使用者调用了delete p; 那么万一类的实现者重载了delete, 这两个delete根本不通用怎么办。
疑问2的补充:
我不同意他的理由。虚析构函数和其他虚函数的实现本没有什么区别。或者说标准本没规定在实现他们上需要有什么区别。
我理解是这样的,在C++里面new和delete必须是对应的。怎么样new出来的东西,就该怎么delete.
假设类的实现者使用如下的方式创建类实例
B *p = new B;
B *pp = new B[10];
那么类的使用者怎么调用delete呢? 所以,类的销毁只能交给类的实现者来做。
还有,delete是个操作符(operator),他本身不是虚函数。delete的逻辑是这样的
先调用类的析构函数
然后调用operator delete去回收内存。
(注:C++中delete和operator delete是两个东西,delete不可被重载,而operator delete可以被重载,同样的也存在new/operator new)
既然operator delete可以被重载,那么问题就出来了。类的使用者的operator delete不一定能够和类的实现者的operator new匹配。
既然不该由类的使用者销毁对象实例,那么也就没有理由把析构函数作为虚函数了,否则类的使用者调用了析构函数,回头类的实现者再调用一次析构函数不就麻烦了。