C ++, нужна причина ошибки: невозможно преобразовать параметр 1 из 'char *' в 'const char * &' - PullRequest
12 голосов
/ 21 октября 2011

Когда мы не можем преобразовать указатель на символ -> TO-> ссылку на указатель на постоянный символ

Мне интересно узнать причину синтаксической ошибки, когда мы вызываем foo_ptr.Когда foo_char разрешено, почему бы не foo_ptr.
[Обновление 1.] Я был бы рад узнать причину, по которой foo_char() работает, почему foo_ptr() не работает .. Что происходит, когда на картинке появляется указатель.

[Обновление 2.] Также не работало в компиляторе Dev C ++ версии 4.9.9.2 ..

//code
//OS : Win XP
//Env: VC++ 2008 

//NOT ALLOWED
void foo_ptr(const char * & ptr) //reference to a pointer to a constant character         
{         
        return;         
}        


//allowed        
void foo_char(const char & p_Char) //reference to a constant character        
{         
        return;        
}        

int main()        
{        
        char ch = 'd';        
        char *ptr =  "anu";        

        foo_char(ch);         
        foo_ptr(ptr); //NOT ALLOWED syntax error, vc++, 2008        

        return 0;        
}        

Ответы [ 3 ]

10 голосов
/ 21 октября 2011

Предположим, у вас было

void foo_ptr(const char * & ptr)
{         
    ptr = "readonlystring";
}        

Теперь вы называете его как

    char *ptr;
    foo_ptr(ptr);
    *ptr = 0;

Предположим, что ошибки не возникли.Вы пишете в строку только для чтения, нарушая систему типов без каких-либо приведений.

Это в основном CV-версия Почему указатель на производный класс не может быть передан функции, ожидающейссылка на указатель на базовый класс? .

2 голосов
/ 21 октября 2011

Пересмотрено с большим количеством примеров: Раймонд Чен дает правильный ответ.Передавая неконстантный указатель (char *) в качестве ссылочного параметра константного указателя (foo_ptr(const char * &param)), вы рискуете вернуть тип константного указателя (const char *), и компилятор не позволит вам сделать это.

Вот пример Раймонда Чена , но я попытался объяснить, как все пойдет не так, если он скомпилируется, добавив дополнительные комментарии и код:

void foo_ptr(const char * & ptr)
{         
    //Valid assignment, and the char * is now pointing to a const
    //array of "readonlystring"
    ptr = "readonlystring";
}   

...
//inside main
char *ptr = malloc(10*sizeof(char));
//See you can edit ptr, it's not const.
ptr[0] = 'a';
ptr[1] = 'b';
//this should not compile, but lets assume it did..
foo_ptr(ptr);
//Oh no, now ptr[0] is 'r' inside of constant memory,
//but now since ptr isn't declared const here I can overwrite it!
//But luckily most (all?) compilers actually fail to compile this code.
ptr[0] = 'b';

Но если выизмените ваш параметр, чтобы вы не могли повлиять на значение, на которое указывает указатель, тогда компилятор пропустит вас неконстантно, потому что нет никакой вероятности, что будет возвращен константный указатель.

Поместив ключевое слово const ПОСЛЕ * в замедление вашего параметра, вы делаете именно это.Это означает изменение:

void foo_ptr(const char * & ptr)

на

void foo_ptr(const char * const & ptr)

, и ваш компилятор будет счастлив.

Теперь вы не сможете сделать что-то вроде ptr = "readonlystring" в приведенном выше примере, потому что это никогда не скомпилируется.Исходя из вашего вопроса, все должно быть в порядке, потому что вы не сможете выполнить присваивание const char & в исходном примере.

0 голосов
/ 21 октября 2011

Вы никогда не должны назначать строковый литерал указателю, не являющемуся const char, как здесь:

 char *ptr =  "anu";        

Измените вышеприведенный код на правильный:

 const char *ptr =  "anu";        

... и я думаю, вы обнаружите, что ваши проблемы решены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...