由于我来自高级Java的C语言,那里没有像const
这样的类型查询器,所以为了使类型不可变,我们必须声明其所有成员为final,并确保成员本身是不可变的
根据合同,在C中,我们有类型quialifier const
。
更具体地说,让我提供一个我目前坚持的例子。我有以下
application.h
:
struct application_config_t{
int poll_interval;
int compression_ratio;
//other config parameters
};
struct application_t{ //This structure make me confused
void (*run_application)(struct application_t*);
void (*stop_application)(struct application_t*);
};
struct application_t* create_app(const struct application_config_t);
void release_app(struct application_t*);
我不确定如何定义application_t
结构。它的唯一目的是使用run_application
运行actaul并使用SIGINT
处理stop_application
以执行正常关闭,然后在stop_application
返回后调用release_app(struct application_t*)
来执行释放内存。
我有以下几种情况可供选择:
I 。不变的application_t
struct application_t{
void (*const run_application)(struct application_t*);
void (*const stop_application)(struct application_t*);
}
我认为这很好,因为一旦创建应用程序就不应对其进行修改。但是创建这样一个不变的结构无论如何都要进行memcpy
调用...
II 。创建应用程序时将变量application_t
声明为
const struct application_t* create_app(const struct application_config_t);
这很好,但是我想在struct application_t*
返回后释放stop_application
所指向的内存。释放struct application_t*
意味着appliaction_t
并不是真正的const
。用法如
struct application_config_t cfg;
//...
const struct application_t *app_ptr = create_app(cfg);
(app_ptr -> run_application)(app_ptr);
release_app((struct application_t *) app_ptr); //const cast
需要强制使用const
进行强制转换。
答案 0 :(得分:3)
发布struct application_t *意味着应用并不是真正的常量
实际上是。客户端代码无法对其进行更改,并且无论如何都应将其移交给release_app
之后再使用。它在整个生命周期中都是const
,并且如果release_app
被指向const的指针接受,则它在语义上是正确的(只需在release_app
内部进行强制转换)。
为什么我说这在语义上是正确的?因为当create_app
为该结构分配空间并对其进行初始化时,它不是其中的const
了吗? const
稍后会作为合同的一部分添加。因此,在release_app
中接受const指针只是遵循您已经建立的相同协定。 API对知道存储可以更改的事实并没有违反合同。