考虑一个简单的、可重用的库。它有一个用于当前状态的对象,以及一个用于为其提供输入的回调函数。
typedef struct Context_S Context_T;
typedef size_t (*GetBytes_T) (Context_T * ctx, uint8_t * bytes, size_t max);
struct Context_S {
GetBytes_T byteFunc;
void * extra;
// more elements
};
void Init(Context_T * ctx, GetBytes_T func);
int GetNext(Context_T * ctx); // Calls callback when needs more bytes
用户可能需要一些额外的回调数据(如文件指针)。库提供了具有 1 个额外指针的函数:
void SetExtra(Context_T * ctx, void * ext); // May be called after init
void * GetExtra(Context_T const * ctx); // May be called in callback
但是,如果用户额外数据是常量,则需要他在设置数据之前丢弃常量。我可以更改函数以获取/返回 const,但是如果数据不应该是常量,这将需要在回调中进行额外的强制转换。
void SetExtra(Context_T * ctx, void const * ext);
void const * GetExtra(Context_T const * ctx);
第三种选择是在函数调用中隐藏强制转换:
void SetExtra(Context_T * ctx, void const * ext);
void * GetExtra(Context_T const * ctx);
在这种情况下隐藏演员表是个好主意吗?
我试图在可用性和类型安全之间找到平衡。但是由于我们使用的是void*
指针,所以很多安全性已经消失了。
还是我忽略了一些值得考虑的事情?