Ответ 1
Вам необходимо защитить содержимое на обоих уровнях разыменования указателя. С помощью const char**
вы могли бы фактически изменить содержимое первого разыменования.
char *tmp = "foo"; //Deprecated but it 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 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
}
Компилятор не допускает неявное преобразование в такие "частично" защищенные типы указателей. Разрешение такого преобразования может иметь неприятные последствия, как описано в c++faq
, о котором говорится в комментарии от @zmb. В этом ответе также говорится, как вы могли нарушить constness объекта, если это было разрешено, используя примеры 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;
}
На самом деле существует множество вопросов и ответов на этот вопрос. Например:
- неверное преобразование из 'char ** в' const char **
- Почему я получаю сообщение об ошибке 'float ** to' const float **?
РЕДАКТИРОВАТЬ: У меня 1-й пример неправильный. Спасибо за указание!