2013-08-16 164 views
21

在C++中,为什么不能合格一个char**作为参数传递给接受const char**的函数,当从char*const char*一个转换是可能的,如下面的C++:字符**为const char **转换

void f1(const char** a) 
{ 

} 

void f2(const char* b) 
{ 

} 

int main(int argc, char const *argv[]) 
{ 
    char* c; 

    f1(&c); // doesn't work 
    f2(c); //works 

    return 0; 
} 

编译器输出

 
test.cpp: In function 'int main(int, const char**)': 
test.cpp:15:10: error: invalid conversion from 'char**' to 'const char**' [-fpermissive] 
test.cpp:1:6: error: initializing argument 1 of 'void f1(const char**)' [-fpermissive] 
+11

http://www.parashift.com/c++-faq/constptrptr-conversion.html – zmb

+0

@zmb一如既往,强大的C++常见问题解答 –

回答

22

您需要保护的内容上的指针的非关联化两个层次。有了const char**,你实际上可以在第一次取消引用中修改内容。

char *tmp = "foo"; //Deprecated but it's ok for the example 
void f1(const char** a) 
{ 
    a[0] = tmp;  //this is legal 
    a[0][1] = 'x'; //this is not 
} 

而这很可能不是目的。它应该看起来像这样:

char *tmp = "foo"; //Deprecated but it's ok for the example 
void f1(char const* const* a) 
{ 
    a[0] = tmp; // this is not legal any more 
    a[0][1] = 'x'; // this still upsets compiler 
} 

编译器不允许隐式转换为这种“部分”保护的指针类型。允许这种转换可能会产生令人讨厌的后果,如在@zmb评论中指出c++faq中所讨论的那样。这answer也引用如果这是允许的,使用char示例,如何违反对象的常量

但可以隐式转换为“完全”保护指针,如代码编译下面的第二个代码示例中所示。

void f1(char const* const* a){} 
void f2(const char* b){} 
int main(int argc, char const *argv[]) 
{ 
    char* c; 
    f1(&c); // works now too! 
    f2(c); // works 
    return 0; 
} 

其实在这个问题上还有一堆问题和答案。 E.g:

  1. invalid conversion from ‘char**’ to ‘const char**’
  2. Why am I getting an error converting a ‘float**’ to ‘const float**’?

编辑:我得到的第一个例子错了位。感谢您指出!

+0

当您知道有像这样的多个问题时,而不是回答它,将其标记为伪装更合适,不是吗? – legends2k

+0

既然它有6个回应,也许它有一些我看不到的原始元素。我也标记了它。是不是真的很糟糕,我认为其他问题是相似的,但不完全一样?即使你说“可能重复”,也不是一个确定的。其实我花更多的时间来写这个评论比回答(原文如此!) – luk32

+0

当然不是那么糟糕,这就是为什么我没有施加压力,我只是问,寒意:)哦,我没有说'可能重复'完成当有人第一次对它进行标记时,它会自动通过。 – legends2k