2013-06-18 8 views
6

chciałbym wywołać następujący kod w C++, których nie mogę zmienić:Jak uniknąć przestarzałej konwersję z ciągiem stałym do „char *” w C++

void getAge(char *name) 
{ 
// do something 
} 

Kiedy ja to nazywam z getAge("hello");, ma następujące ostrzeżenie:

warning: deprecated conversion from string constant to 'char*' 

, ale nie ma żadnego ostrzeżenia w kodzie C. Jaka jest różnica i jak zmienić wywołanie, aby uniknąć ostrzeżenia w C++?

+4

Czy parametr funkcji ma postać "const char *"? –

+0

nie, jest to funkcja zdefiniowana przez innych, nie można zmienić – user2131316

+1

W takim przypadku należy rzucić argument. –

Odpowiedz

17

funkcja [...] nie może być zmieniony

Następnie napisać otoki wokół funkcji i skopiować ciąg - lub, jeśli czujesz się szczęśliwy (= wiesz że ciąg wygrał” t być modyfikowane wewnątrz pierwotnej funkcji), wyraźnie odrzucił const-ności:

void getAge(char const* name) { 
    the_namespace::getAge(const_cast<char*>(name)); 
} 

Jeśli nie masz pewności, czy funkcja modyfikuje jego parametry, należy użyć coś jak następuje - jednak, jeśli to przypadek wówczas wywołanie funkcji z literałem tekstowym (getAge("hello")) i tak byłby nieważny.

void getAge(char const* name) { 
    std::string buffer(name); 
    the_namespace::getAge(&buffer[0]); 
} 

Tutaj możemy skopiować ciąg do modyfikowalnego bufora i przekazać adres do pierwszego znaku do oryginalnej funkcji.

+0

@EricPostpischil A co oznacza "skopiuj ciąg", w przeciwnym razie. –

0

Możesz spróbować getAge((char*)"hello").

+1

Tylko jeśli wiesz, że funkcja nie spróbuje zmodyfikować napisu. I naprawdę powinieneś używać rzutów C++. –

+0

To jest oznaczone 'C++'. –

0

w C++ można napisać to tak, void getAge(string name) { // do something } a także dołączyć plik nagłówka #include<string> ponieważ używasz ciąg teraz

+0

Metoda void getAge() nie może zostać zmieniona – user2131316

+1

Przeczytaj pytanie, proszę ... – nouney

+1

@nouney, informacja "nie można zmienić" nie została jeszcze podana w pytaniu, ale tylko w komentarzach. – Steed

2

Najbezpieczniejszym sposobem jest skopiowanie ciąg, a następnie wywołać funkcję C:

void getAgeSafe(const char* name) 
{ 
    std::vector<char> tmp = name? 
    std::vector<char>(name, name+1+strlen(name)) 
    :std::vector<char>(); 

    getAge(tmp.data()); 
} 

i zadzwoń pod numer getAgeSafe ze swojego kodu C++.

mniej bezpieczne

sposób, który opiera się na kodzie C nigdy zmieniający char* name byłoby const_cast ponownie w funkcji „owijania”:

void getAgeUnsafe(const char* name) 
{ 
    getAge(const_cast<char*>(name)); 
} 

ale tym razem nazwa jest bardziej przerażające, jak to operacja. Jeśli wywołasz getAge ze stałym ciągiem czasu kompilacji, takim jak "bob", jeśli getAge modyfikuje jego wejście, nieokreślone wyniki zachowania (tak jest w C i C++ - C++ przynajmniej ostrzega o tym).

+0

'c_str()' zwraca 'const char *', więc otrzymasz to samo ostrzeżenie. Przekazanie 'i name [0]' będzie jednak działać. – SirGuy

+0

@GuyGreer oops, naprawiony. Nawet 'data()' jest 'const' dla' std :: string', więc zamiast tego zbudował bufor 'std :: vector '. (Nie jestem pewien, czy 'i name [0]' jest gwarantowane, że jest zakończone znakiem null przez standard?) – Yakk

+0

@Yakk Jest w C++ 11 (zakończenie zerowe nie było problemem przed - przynależność pamięci była). Twój obecny kod jest niepotrzebnie zawiłe w mojej opinii; po prostu użyj odpowiedniego konstruktora, aby zainicjować wektor (oczywiście sprawi to, że kontrola zerowa będzie niemożliwa lub przynajmniej trudniejsza). –

Powiązane problemy