看COM本质论做的总结
1.1 软件分发和C++
class FastString {
char* m_psz;
public:
FastString(const char *psz);
~FastString();
int Length(void) const;
int Find(const char *psz)const;
};
#include "faststring.h"
#include <string.h>
FastString::FastString(const char *psz)
:m_psz(new char[strlen(psz) + 1])
{
strcpy(m_psz, psz);
}
FastString::~FastString()
{
delete[] m_psz;
}
int FastString::Length(void) const
{
return strlen(m_psz);
}
int FastString::Find(const char *psz) const
{
// O(1)
return 0;
}
假如一个faststring.obj 需要16MB的空间,有三个应用程序ABC都要用到这个类,的方法,那虚拟内存就需要48MB;
另一种情况是,一旦类库的厂商发现了FastString类中的缺陷,我们只能全部重新编译ABC三个应用程序;
1.2 动态链接和C++
解决上面的问题,就是将FastString独立为dll类
#ifndef EXPORT_IMPORT_API
#ifdef MAKING_LIBRARY
#define EXPORT_IMPORT_API __declspec(dllexport)
#else
#define EXPORT_IMPORT_API __declspec(dllimport)
#endif
#endif
class EXPORT_IMPORT_API FastString {
char* m_psz;
public:
FastString(const char *psz);
~FastString();
int Length(void) const;
int Find(const char *psz) const;
};
库的编译add_definitions(-DMAKING_LIBRARY)
应用程序调用不需要define MAKING_LIBRARY
1.3 C++和可移植性
到此,以上用dll的形式,你将面临C++的基本弱点: C++缺少二进制一级标准。
由于FastString 引入库lib和引出符号dll使用了创建该dll的编译器(比如Gnu C++)的名字改编方案,所以使用其它编译器(比如Borland C++)产生的客户将无法与引入库lib成功链接。
消除名字改编现象的经典技术是使用 extern “C”, 但是这项技术对于FastString这种情况并没有用,因为它引出的是成员函数,而非全局函数。
有一项技术能够减轻这个问题,就是在客户的链接器上,使用模块定义文件(Module Definition File, 通称为DEF文件)
1.4 封装性和C++
假设此时你需要优化一下FastString类,增加了一个成员变量 int m_len(如下)
class EXPORT_IMPORT_API FastString {
const int m_len; //add
char* m_psz;
public:
FastString(const char *psz);
~FastString();
int Length(void) const;
int Find(const char *psz) const;
};
虽然类的公共接口没有变,但实际上sizeof(FastString)发生了变量,由原来的4变成了8。如果直接替换FastString.dll,这样新增的4字节内存就可能被应用程序其它地