2013-04-09 17 views
7

Mam mały problem z moim konstruktorem. W moim pliku nagłówka oświadczam:Błąd C++: Niezgodne typy w przypisywaniu "char *" do "char [2]

char short_name_[2]; 
  • i innych zmiennych

W moim konstruktora:

Territory(std::string name, char short_name[2], Player* owner, char units); 
void setShortName(char* short_name); 
inline const char (&getShortName() const)[2] { return short_name_; } 

w moim pliku cpp:

Territory::Territory(std::string name, char short_name[2], Player* owner, 
        char units) : name_(name), short_name_(short_name), 
        owner_(owner), units_(units) 
{ } 

Mój błąd:

Territory.cpp: In constructor ‘Territory::Territory(std::string, char*, Player*, char)’: Territory.cpp:15:33: error: incompatible types in assignment of ‘char*’ to ‘char [2]’

już zorientowali się, że char[2] <=> char* ale nie jestem pewien, jak obsługiwać ten temat mojego konstruktora i uzyskać/ustawiaczy.

+1

'Już wymyśliłem, że char [2] <=> char *' not really. – Rapptz

+0

ale myślałem, że kompilator C++ jest char [2] równoważne char *?! Naprawdę nie mam pojęcia, jak zainicjować tego konstruktora i getters corretly ... – vicR

+1

Tablice i wskaźniki są * bardzo * różne rzeczy. Przeczytaj sekcję 6 w [comp.lang.c FAQ] (http://www.c-faq.com/); zasady w tej dziedzinie są zasadniczo takie same dla C i C++. –

Odpowiedz

12

Surowe tablice w C++ są dość denerwujące i najeżone niebezpieczeństwem. Dlatego też, chyba że masz bardzo dobry powód, powinieneś użyć std::vector lub std::array.

Po pierwsze, jak powiedzieli inni, char[2] to nie to samo co char*, a przynajmniej nie zwykle. char[2] jest tablicą o rozmiarze 2 z char i char* jest wskaźnikiem do char. Często stają się zdezorientowani, ponieważ tablice ulegają rozpadowi do wskaźnika do pierwszego elementu, gdy tylko zajdzie taka potrzeba. Tak to działa:

char foo[2]; 
char* bar = foo; 

Ale odwrotna nie:

const char* bar = "hello"; 
const char foo[6] = bar; // ERROR 

Dodanie do zamieszania, podczas deklarowania parametrów funkcji, char[] jest równoważna char*. Tak więc w konstruktorze parametr char short_name[2] jest naprawdę char* short_name.

Innym dziwactwem tablic jest to, że nie mogą być kopiowane tak jak inne typy (to wyjaśnienie, dlaczego tablice w parametrach funkcji są traktowane jako wskaźniki).Tak na przykład mogę nie zrobić coś takiego:

char foo[2] = {'a', 'b'}; 
char bar[2] = foo; 

Zamiast muszę iteracyjne nad elementami foo i skopiować je do bar, lub korzystać z niektórych funkcji, która robi to dla mnie taki jak std::copy:

char foo[2] = {'a', 'b'}; 
char bar[2]; 
// std::begin and std::end are only available in C++11 
std::copy(std::begin(foo), std::end(foo), std::begin(bar)); 

Więc w konstruktora trzeba ręcznie skopiować elementy short_name do short_name_:

Territory::Territory(std::string name, char* short_name, Player* owner, 
        char units) : name_(name), owner_(owner), units_(units) 
{ 
    // Note that std::begin and std::end can *not* be used on pointers. 
    std::copy(short_name, short_name + 2, std::begin(short_name)); 
} 

Jak widać, wszystko to jest bardzo denerwujące, więc jeśli nie masz bardzo dobrego powodu, powinieneś użyć std::vector zamiast surowych tablic (lub w tym przypadku prawdopodobnie std::string).

2

Gdy funkcja chce tablicy jako argumentu, otrzymuje zamiast niej wskaźnik do pierwszego elementu tablicy. Tego wskaźnika nie można użyć do zainicjowania tablicy, ponieważ jest to wskaźnik, a nie tablica.

Możesz napisać funkcje, które akceptują referencje do tablic jako argumentów:

void i_dont_accept_pointers(const char (array&)[2]) {} 

tu problem jest to, że to odniesienie tablica nie może być używany do inicjacji kolejną tablicę.

class Foo { 
    char vars[2]; 
    Foo(const char (args&)[2]) 
    : vars(args) // This will not work 
    {} 
}; 

C++ 11 wprowadza std::array do eliminiate ten i inne problemy związane z tablic. W starszych wersjach będziesz musiał iterować elementy tablicy i kopiować je pojedynczo lub użyć std::copy.