假设您是创建 Windows API 的开发人员。您已经定义、记录和发布了一些 API 调用集。您当前的许多 API 调用都接受指向结构的指针作为输入参数,以允许在没有大量输入参数的情况下传递许多输入值。
现在开发人员开始为您的操作系统编写代码。
几年后,您决定创建新版本的 Windows 操作系统。不过你有一些要求:
- 为以前的操作系统版本编译的程序仍必须在您的较新操作系统上执行 - (API 必须向后兼容)。
- 您想扩展您的 API -(添加了新的 API 调用)。
- 您希望允许开发人员使用他们现有的代码(他们为旧窗口编写的代码)并允许他们在新操作系统上编译和执行它。
好的 - 为了使您的旧程序能够工作,您的新 API 必须具有相同的例程和相同的参数等。
现在如何扩展你的 API?您可能会添加新的 API 调用,但如果同时 - 想要使用旧代码并使用一些新奇的功能而不对您的代码进行太多更改怎么办?
通常 API 例程需要很多信息,但是创建具有许多形式参数的例程很不方便。这就是为什么正式的参数之一是一个指向包含要传递给例程的属性的结构的指针很常见的原因。这使得 API 扩展变得容易。例如:
您的旧代码:
struct abc
{
int magicMember; // ;-)
int a;
int b;
int c;
};
void someApiCall( struct abc *p, int blaBla );
现在,如果您决定通过提供更多信息而不更改例程的签名来扩展您的“someApiCall”,那么您只需更改您的结构。
你的新代码:
// on new OS - defined in a header with the same name as older OS
// hence no includes changes
struct abc
{
int magicMember; // ;-)
int a;
int b;
int c;
int new_stuff_a;
int new_stuff_b;
};
void someApiCall( struct abc *p, int blaBla );
您保留了例程的签名,同时允许新旧代码工作。唯一的秘密是magicMember,您可以将其视为结构的修订号,或者-如果在新版本中您只是添加新成员-结构的大小。您的“someApiCall”两种方式都将能够区分两种“相同”结构,并且您将能够从旧代码和新代码执行该 API 调用。
如果一个人很挑剔——他可能会说这些不是相同的结构。确实不是。它们只是具有相同的名称以防止更多的代码更改。
对于实际示例,请检查RegisterClassEx API 调用和它需要的 WNDCLASSEX 结构