Подтвердить что ты не робот

С++: char ** to const char ** преобразование

В С++ почему невозможно передать char** в качестве аргумента функции, принимающей const char**, когда возможно преобразование из char* в 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]
4b9b3361

Ответ 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;
}

На самом деле существует множество вопросов и ответов на этот вопрос. Например:

РЕДАКТИРОВАТЬ: У меня 1-й пример неправильный. Спасибо за указание!