2013-09-05 3 views
0

Так что я очень новичок в C++ и имею фон в динамических языках, это, вероятно, вопрос новичков. Я пытался написать вековое упражнение, см ниже:C++ - Невозможно преобразовать из 'char []' в 'char []'

class Person 
{ 
public: 
    Person(char n[], int a) {   
     name = n; 
     age = a; 
    } 

    int age; 
    char name[]; 

}; 

int main(int argc, char const *argv[]) 
{ 
    Person p("John", 25); 
    return 0; 
} 

Это бросает ошибку:

main.cpp(8) : error C2440: '=' : cannot convert from 'char []' to 'char []' 
     There are no conversions to array types, although there are conversions 
to references or pointers to arrays 

Почему нужно конвертировать из одного типа? Это мой полный код и полная ошибка, кстати. Любая помощь приветствуется!

+3

Это является плохим (вводит в заблуждение, заблуждение) сообщение об ошибке. Тем не менее, это незаконная ошибка. Вы даже не можете использовать 'char name [];' в структуре или классе, но вы еще не дошли до этой ошибки. Вам нужно определить размер для массива или использовать «std :: string» или, возможно, (но, вероятно, не очень целесообразную) игру с символом 'char * name;'. Однако, если вы выберете 'char * name', вам придется иметь дело с распределением во время строительства и выпуска во время уничтожения, а также беспокоиться о назначении и создании копии, а также перемещать семантику и безопасность исключений. –

+0

Использование компилятора Microsoft C++, который, похоже, вызывает очень запутывающие сообщения об ошибках. Думаю, они ожидают, что вы будете использовать Visual Studio, а не командную строку. – EpicPineapple

ответ

3

Существует тип называется char [], но это тип неполный массив который несколько сложная тема. Если он компилируется в строгом режиме, компилятор сообщил бы, что неполный массив не может быть членом класса, и это должно предотвратить полученную ошибку. Но на самом деле вы наткнулись на расширение GCC, которое редко совместимо с C++, поскольку оно требует выделения памяти на malloc.

В любом случае, C++ действительно имеет строки переменной длины в библиотеке, хотя и не как «родной» тип. Вам необходимо включить <string>, и он называется std::string.

#include <string> 

class Person 
{ 
public: 
    Person(std::string n, int a) {   
     name = n; 
     age = a; 
    } 

    int age; 
    std::string name; 

}; 

int main(int argc, char const *argv[]) 
{ 
    Person p("John", 25); 
    return 0; 
} 
1

Массивы не могут быть назначены. Вы должны копировать элементы по каждому индексу на другой итеративно. Для массивов символов вы можете использовать strcpy.

int a[5], b[5]; 

a = b; // Error 

Необходимо указать размер массива. Используйте std::string вместо работы с массивами символов.

+0

У меня создалось впечатление, что у C++ не был тип 'string'? – EpicPineapple

+1

Где у вас такое впечатление? На самом деле это называется ... 'string'. –

+0

Конечно, они находятся на C. Но если вы используете C++, используйте 'string'. –

0

Я скомпилировать пример кода в г ++ и что происходит, становится немного понятнее:

so.cpp:5:16: error: incompatible types in assignment of ‘char*’ to ‘char [0]’ 

Этот массив нулевой длины является «гибкий элемент массива». Он должен быть последним членом данных класса, и, как и в случае с другими массивами, его нельзя назначить. Если вы не можете использовать std::string по какой-то причине, например, если модуль ваш C++ должен представить определенный API для модулей C, попробуйте изменить последнюю строку из Person следующим образом:

const char *name; 

Это приведет к обработке программа с предупреждением Const-правильностью, который может быть закреплен путем изменения первой строки конструкторы:

Person(const char n[], int a) { 

окончательной программа, которая компилируется без предупреждений в г ++:

#include <cstdio> 
class Person 
{ 
public: 
    Person(const char n[], int a) {   
     name = n; 
     age = a; 
    } 

    int age; 
    const char *name; 

}; 

int main(int argc, char const *argv[]) 
{ 
    Person p("Jack", 14); 
    std::puts(p.name); 
    return 0; 
} 
+0

Обратите внимание, что «гибкие элементы массива» являются расширением GCC (G ++) до стандарта C++ 11. ('g ++ -std = C++ 11 -pedantic' должен показать это.) Они являются частью C99 и C11, но это другой язык. –

+0

Обратите внимание, что хотя ваш конструктор 'Person' работает нормально с' 'Jack '' в качестве инициализатора, если кто-то использует: 'str :: string j =" Jack "; Гнездо пользователя (j, 14); j = «Jill»; ', вероятность довольно высокая, что указатель в' j.name' больше не содержит действительного указателя на '' Jack ''.Он может содержать допустимый указатель на '' Jill'', или может содержать недопустимый указатель (и который он содержит, вероятно, не определен). –

1

Есть несколько ошибок в коде:

  1. Тип n является char*: это не массив, но указатель. Вы не можете передавать встроенные массивы в качестве параметров значения. Вы могли бы передать это как ссылку, хотя, например. используя char const (&n)[5] (я доберусь до const).
  2. Даже если вы передаете массив name - массив без элементов и фактически незаконный! Вы должны использовать положительный размер для массива.
  3. Предположим, что вы объявили name как член типа char name[5]; и n в качестве ссылки на массив, вы все равно не сможете их назначить, потому что массивы не могут быть назначены. Можно, однако, копировать их, используя, например,

    std::copy(std::begin(n), std::end(n), std::begin(name)); 
    
  4. Тип строкового литерала является char const[N] с N является количество символов в строке буквальным. Вы не можете назначить это значение char*. В C++ 03 назначение должно было поддерживаться, но устарело, а в C++ 11 назначение больше не разрешено (хотя вполне вероятно, что компилятор разрешит его, если вы не включите строгий режим).

  5. Не ошибка, а заметка: вы должны инициализировать свои члены, где это возможно, в списке инициализаторов членов, например. (Предполагается, что элемент name имеет подходящий тип):

    Person(char const* n, int a) 
        : age(a) 
    { 
        strncpy(this->name, n, sizeof(this->name)); 
    } 
    
0

Вот ошибка, я получаю от г ++

$ g++ -Wall example.cc -o example 
example.cc: In constructor ‘Person::Person(char*, int)’: 
example.cc:5:16: error: incompatible types in assignment of ‘char*’ to ‘char [0]’ 
example.cc: In function ‘int main(int, const char**)’: 
example.cc:16:24: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] 

Если я заменяю char n[] и char name[] с char *n и char *name, вы получите

$ g++ -Wall example.cc -o example 
example.cc: In function ‘int main(int, const char**)’: 
example.cc:16:24: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] 

Я не уверен, почему компилятор char* лучше в этом случае, но имеет смысл использовать char*, представляя строки в Генеральная.

Поскольку вы пишете на C++, тип std::string обычно предпочтительнее, поскольку он более безопасен по типу, чем char*. Это сделает код более компилируемым.

Будет ли все это в виду, я хотел бы написать следующий код

#include <string> 

class Person 
{ 
public: 
    Person(std::string n, int a) {   
     name = n; 
     age = a; 
    } 

    int age; 
    std::string name; 

}; 

int main(int argc, char const *argv[]) 
{ 
    Person p("Jack", 14); 
    return 0; 
} 
+0

Re "имеет смысл использовать char * при представлении строк в целом". Нет. В общем, имеет смысл использовать 'std :: string' при представлении строк в C++. –