2013-03-20 4 views
1

Я пишу программу, которая должна обрабатывать как строки c (char *), так и строки C++ (std :: string). Я остановился на примере ниже.C++ неявное преобразование строки в char * соответствует неправильной сигнатуре функции

#include <iostream> 
#include <string> 

void hello(std::string s) { 
    std::cout << "STRING FUNCTION" << std::endl; 
} 

void hello(char* c) { 
    std::cout << "CHAR FUNCTION" << std::endl; 
} 

int main(int argc, char* argv[]) { 
    hello("ambiguous"); 
    hello((std::string)"string"); 
    hello((char*)"charp"); 

    return 0; 
} 

Когда я компилирую эту программу, я получаю предупреждение:

test.cpp:14: warning: deprecated conversion from string constant to ‘char*’ 

относительно первого вызова hello. Запуск программы дает:

CHAR FUNCTION 
STRING FUNCTION 
CHAR FUNCTION 

показывает, что первый вызов hello сопрягает подпись hello(char* c).

Мой вопрос, если, как с программой ++, строковым ("ambiguous") является станд :: строка, почему он будет брошен в char*, а затем сопоставить функцию hello(char* c), а не оставаться в станд: : строка и соответствие hello(std::string s)?

Я знаю, что могу прагма или -что-то из предупреждения (и что я могу использовать char * для строки без беспокойства), но я хочу знать, почему компилятор даже потрудился сделать это приведение, и если есть способ скажи это не. Я компилирую с g ++ 4.4.3.

спасибо.

+8

Строковый литерал не является 'std :: string'. Он имеет тип 'const char [N]'. – juanchopanza

+0

Строковый литерал ('' неоднозначный '') - это ** не ** строка std ::. Он следует тому же соглашению, что и строки C. –

+1

В случае, если он еще не встретился, измените 'char *' на 'const char *'. – chris

ответ

4

Строковые литералы как "ambiguous" не типа std::string. std::string - это только тип библиотеки, без языковой магии. Тип строкового литерала - это фактически const char[N], где N - это длина литерала.

По историческим причинам (обратная совместимость) строковые литералы будут неявно преобразовывать в char* (нарушая const-correctness). Это встроенное преобразование предпочтительнее «пользовательского» преобразования в std::string, поэтому оно вызывает функцию char* и дает вам предупреждение.

Если изменить подпись hello к hello(const char* c) это, вероятно, не даст вам предупреждение больше (но по-прежнему не будет вызывать версию std::string, для этого вам нужно вручную отливов).

0

Вы не правы: «как программа C++, строковый литерал, (» неоднозначной «) является станд :: строка»

+7

Хорошо знать, что ОП ошибочен, но было бы еще лучше узнать, какой правильный ответ :) – Praetorian

0

("неоднозначный") не является std :: string, это массив символов.

Именно поэтому его вызывающий недействительный привет (char * c).