Инициализируйте System :: String ^ с помощью литерала, но не string :: c_str () или char [] - PullRequest
1 голос
/ 27 января 2012

Я недавно начал изучать .net и Windows API, и сейчас пишу класс, который сообщает о последовательном порте.

Чтобы записать строку в последовательный порт, я используюWriteLine функция, которая принимает параметр, System::String^.Я хотел бы знать, возможно ли инициализировать System::String^ из std::string.

Я заметил, что могу сделать следующее:

serialPort->WriteLine("stuff");

, но я не могуделать:

std::string data = "stuff";
serialPort->WriteLine(data.c_str());

также я не могу сделать:

char data[] = "stuff";
serialPort->WriteLine(data);

или

char* data = "stuff";
serialPort->WriteLine(data);

Может ли кто-нибудь дать мне знать, что здесь происходит?VS как-то конвертирует литерал в его собственную вещь, когда я передаю его?

Наконец, я не уверен, что выбрал правильные теги для этого, так как не знаю, к чему это относится.

1 Ответ

3 голосов
/ 27 января 2012

Вы всегда можете вызывать функции со строковыми литералами, потому что компилятор автоматически преобразует их в значение соответствующего строкового типа.

Проблема здесь в том, что вы пытаетесь смешать компоненты .NET Framework (System::String) со стандартным строковым типом C ++ (std::string), и они просто не очень хорошо сочетаются. Функции .NET, которые принимают параметр типа System::String, не записаны или перегружены для приема параметра типа std::string. Если вы работаете с .NET Framework, то вы используете C ++ / CLI, и обычно ожидается, что вы будете использовать строковый тип .NET, а не строковый тип C ++.

Аналогично, стандартные функции C ++ ожидают std::string и ничего не знают о строковом типе .NET Framework. Поэтому, если вы ожидаете вызова функций из стандартной библиотеки C ++, вам следует использовать ее строковый тип.

Строки в стиле C (char[]) - это старый запасной вариант, который вы никогда не захотите использовать при написании кода на C ++. std::string всегда лучший вариант, и он даже предоставляет метод c_str(), который вы уже знаете, который будете использовать при вызове функции API, которая ожидает массив символов. Но, как и другие два строковых типа, этот также не является взаимно конвертируемым.

Одна особенно большая проблема, с которой вы столкнетесь, заключается в том, что типы std::string и char[] принимают только "узкие" (не Unicode) строки, тогда как тип .NET Framework System::String работает только с широкими (Unicode) ) строки. Это добавляет еще один рывок в миксе, когда дело доходит до конверсии. Там нет никакого способа, которым это может быть так просто, как приведение.

Но это не значит, что невозможно конвертировать между типами. На MSDN есть полезный документ, в котором объясняется , как конвертировать строки в различные типы C ++ .

В итоге вы можете преобразовать строки в стиле C в System::String, используя соответствующим образом перегруженный конструктор, который принимает char*:

const char* cString = "Hello, World!";
System::String ^netString = gcnew System::String(cString);
Console::WriteLine(netString);
delete netString;

И затем, конечно, вы можете конвертировать из std::string в System::String, комбинируя описанный выше метод с методом c_str():

std::string stdString("Hello, World!");
System::String ^netString = gcnew System::String(stdString.c_str());
Console::WriteLine(netString);
delete netString;
...