2017-04-25 550 views
0

我正在处理第三方库,在此为了简化代码,我想修改一个结构。将常量参数的const char *成员赋值为新值

有一个第三方结构

struct structure { 
    const char *c; 
    // ... 
}; 

我有一个函数

void prep(const structure *s) { 
    std::string str("hello"); 
    const char *t_c = s->c; 
    s->c = str.c_str(); // structure::c is a const char * 
    handle(s); // makes use of overriden c 
    s->c = t_c; // Set back in case library tries to free/use memory later 
} 

我该怎么做适当的常量铸造这里?

+5

如果你想修改结构,不要把它作为'const'传递。 –

+0

函数签名给我重写的库,我不控制。 – shane

+2

你应该把's'作为非常量或复制's'。如果你选择预制一个'const_cast',你必须确保'handle'和's-> c'的赋值不能抛出,'s'的实例指针实际上不是'const'。强烈建议您尽可能避免使用'const_cast'。 –

回答

2

我假设handle被宣布为void handle(const structure*);

最简单的解决方案是复制s,修改副本,然后将其传递给handle。由于sconst,您知道可能无法对需要传播到原始s的副本进行更改。您也不需要将s->c重设为原始值。

void prep(const structure *s) 
{ 
    structure mycopy(*s); // Make a copy of s 
    std::string str("hello"); 
    mycopy.c = str.c_str(); // structure::c is a const char * 
    handle(&mycopy); // makes use of overriden c 
} 

如果您不能复制structure,考虑为s去除const符修改你的函数声明。如果你只是删除const你会得到以下编译好的函数。请注意,生成的函数不是例外安全的。如果handle引发异常,则将无法将s->c成员重置为其原始值。

void prep(structure *s) 
{ 
    std::string str("hello"); 
    const char *t_c = s->c; 
    s->c = str.c_str(); // structure::c is a const char * 
    handle(s); // makes use of overriden c 
    s->c = t_c; // Set back in case library tries to free/use memory later 
} 

如果一切都失败了,您可能可以使用const_cast作为最后的手段。请确保s未指向实际为const的实例,并确保在s未处于初始状态时不会引发异常。被迫使用const_cast可能是糟糕的设计决策的一个指标。

void prep(const structure *s) 
{ 
    std::string str("hello"); 
    const char *t_c = s->c; 
    const_cast<structure*>(s)->c = str.c_str(); // structure::c is a const char * 
    handle(s); // makes use of overriden c 
    const_cast<structure*>(s)->c = t_c; // Set back in case library tries to free/use memory later 
} 
+0

'try' /'catch' /'rethrow'解决了异常问题。虽然我同意最好完全避免。 –

+0

因为这是回调的函数原型,所以const const是必须的,void callback(const structure * s){prep(s)} void prep(structure * s){...}'不编译 – shane

+0

@ shane“结构”不可复制? –