Проблема в том, что C ++ является строго типизированным языком. Вы должны убедиться, что тип справа от =
совпадает с типом слева (или есть какое-то четко определенное преобразование, которое позволяет компилятору конвертировать между типами).
Итак, нам нужно знать, что такое литералы типов: при использовании двойной кавычки создается строковый литерал типа char const[]
, а при использовании одинарной кавычки создается символьный литерал типа char const
.
Вам придется терпеть меня со стороны const
. Это делает обсуждение намного более сложным, поэтому мы сначала замаскируем его.
Нам также нужно знать, что когда массивы используются в выражениях, они очень легко распадаются на указатели. Таким образом, в большинстве ситуаций тип char const[]
переходит в char const*
.
Это должно работать:
char const* p = "Hello"; // This is valid.
// Both left and right sides have the same type.
// After you consider the array decay into a pointer.
С другой стороны
char const* p = 'H'; // The type on the right is `char const'
// While the type on the right has a pointer in it.
Теперь здесь есть несколько автоматических конверсий.
В исходном C ++ 03 компилятору было разрешено автоматически преобразовывать строковые литералы из char const*
в char*
. Это реликвия из старого языка C, которая не была столь строгой в проверке типов, как C ++ сейчас. Это позволяет для этого:
char* p = "Hello"; // Because there is an auto conversion
// the compiler is allowed to make
// the conversion from one type to another
Обратите внимание, что в более поздних версиях C ++ это преобразование устарело. Таким образом, компилятор предупредит вас, что это опасно (поскольку вы удалили const из типа, для которого вам разрешено изменять его, но базовый объект не может быть изменен, поэтому, если вы попытаетесь, он взорвет программу).
Так почему вы можете назначить char const
на char
?
char x = 'X';
Здесь вы копируете исходный объект char const
в объект типа char
, это совершенно правильно. Вы не можете изменять или изменять буквальное значение, но вам разрешено делать его копии. Таким образом, вы можете легко удалить внешний const
в выражении присваивания.
char const* const y = "Hello";
char const* z = y; // We remove the outer const
// from a pointer. But the inner
// const (of the object being pointed
// at) can not be removed so easily.
// This works because z is allowed to
// to be changed but hold a value a pointer
// to a value that can not be changed.
Глядя на ваш комментарий:
#include <iostream>
void test(char *str)
{
std::cout << str << std::endl;
}
int main()
{
test("Hello"); // This is allowed in C++
// Deprecated still means valid.
// Just not a good idea
// There is a allowed conversion from
// char const* to char* for string literals.
char const* x = "test";
test(x); // This is NOT allowed.
// You can not cast away this const.
}
Примечание: Технически строковый литерал равен char const[]
. то есть массив const char. НО при использовании в выражениях массивы очень легко распадаются на указатели и, следовательно, иногда проще думать о них как о char const*
, но это мышление абстрактно, и вы должны знать точный базовый тип.