Почему следующее задание не работает? Я хотел бы получить объяснение низкого уровня, если это возможно. Кроме того, вот ошибка компилятора, которую я получаю: несовместимые типы при присвоении ‘char *’ к ‘char [20]’
class UCSDStudent {
char name[20];
public:
UCSDStudent( char name[] ) {
//this-> name = name; does not work! Please explain why not
strcopy( this -> copy, copy ); //works
}
};
Потому что когда у вас есть вызов функции, как это UCSDStudent( char name[] )
только адрес массива name
копируется вместо всего массива. Это особенность C \ C ++.
Кроме того name
определяется как char name [20]
не является изменяемым значением lvalue.
относительно strcpy
: это приведет к неопределенному поведению, как будто ваш исходный массив не имеет символа NULL, он скопирует мусор в this->name
тоже. Вы можете прочитать больше о strcpy
Вот
Если вы все еще хотите назначить массив массиву, используйте цикл.
например:
класс UCSDStudent
{
char name[20];
public:
UCSDStudent( char name[] )
{
for(int i = 0; i<20; i++)
{
this-> name[i] = name[i];
}
}
};
Потому что вы присвоили имя как массив, поэтому вы не можете просто скопировать его, и есть 21 счет, который имеет имя. Вы должны использовать «=», чтобы скопировать циклы with, и вы должны определить количество массивов.
for(int i = 0; i<20; i++){
this -> name[i]=name[i];
}
Массивы в стиле c не могут быть скопированы таким образом, если вы хотите
скопировать один, вы должны скопировать содержимое вместо:
int arr1[10] = {1,2,3,4,5,6,7,8,9,10};
int arr2[10];
std::copy(arr1, arr1+10, arr2);
// std::copy() lives in <algorithm>
// content of arr2 is a now copy of arr1
Тем не менее, лучше избегать низкоуровневых функций, таких как массивы в стиле c.
Если то, что вы действительно хотели, было строкой переменной длины, используйте std::string
вместо этого он поддерживает копирование через оператор присваивания.
Если вы действительно хотите массив фиксированной длины, используйте std::array<T,N>
вместо,
он также поддерживает копирование через оператор присваивания.
Также обратите внимание, что рекомендация заключается в том, что имена параметров и имена переменных-членов различны, за исключением конструкторов, в которых используется синтаксис инициализации члена:
#include <string>
class UCSDStudent
{
std::string name;
public:
UCSDStudent( std::string name )
: name(name)
{
}
void SetName( std::string new_name )
{
name = new_name;
}
};
Также обратите внимание, если вы планируете иметь сеттеры и геттеры для всех членов
переменные, могу ли я рекомендовать общедоступные данные, по крайней мере, если класс
не имеет Класс-инвариантный.
Давайте возьмем этот пример.
int arr1[10] = {1,2,3,4,5,6,7,8,9,10};
В случае C ++ имя массива arr1
не получает отдельную ячейку памяти. Это правда, что arr1
вроде хранит расположение памяти arr1[0]
но это больше упрощение. Ссылка на массивы в C ++ осуществляется через таблицу символов. Когда создается массив, то, что на самом деле происходит, соответствует arr1
запись создается в таблице символов во время компиляции, и эта запись содержит информацию о типе данных arr1
ссылается на (который здесь является массивом целочисленного типа) и адрес arr1[0]
, Теперь здесь кроется интересная вещь. Как только запись создана в таблице символов, C ++ не позволяет ее изменять.
Если вы делаете arr1=arr2
То, что вы по сути пытаетесь сделать, это переназначить arr1
к записи, соответствующей arr2
в таблице символов. Но arr1
уже было присвоено какое-то значение в таблице символов. Так что C ++ выдаст вам ошибку.