2010-09-23 2 views
4

Здравствуйте, у меня есть класс накачки, который требует использования переменной-члена, которая является указателем на массив wchar_t, содержащий адрес порта, то есть: «com9».Устаревшее преобразование из строки const. to wchar_t *

Проблема заключается в том, что когда я инициализирую эту переменную в конструкторе, мой компилятор подменяет предупреждение об изношенном преобразовании.

pump::pump(){ 
    this->portNumber = L"com9";} 

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

Я попытался создать массив, а затем установив переменную-член, как это:

pump::pump(){ 
    wchar_t port[] = L"com9"; 
    this->portNumber = port;} 

Но по какой-то причине это делает мою точку Portnumber на «F».

Очевидно, что еще одна концептуальная проблема с моей стороны.

Спасибо за помощь по моим вопросам noobish.

EDIT:

Как запросить определение Portnumber было:

class pump 
{ 
private: 
    wchar_t* portNumber; 
} 

Благодаря ответам он теперь был изменен на:

class pump 
{ 
private: 
    const wchar_t* portNumber; 
} 
+0

Дайте нам определение 'pump :: portNumber', пожалуйста. –

ответ

11

Если portNumber является wchar_t*, он должен const wchar_t*.

Строковые литералы неизменяемы, поэтому элементы const. Существует устаревшее преобразование из строкового литерала в неконстантный указатель, но это опасно. Внесите изменения, чтобы вы сохраняли безопасность типов и не использовали небезопасное преобразование.

Вторая неудача, потому что вы указываете на содержимое локальной переменной. Когда конструктор заканчивается, переменная уходит, и вы указываете на недопустимое местоположение. Использование этого метода приводит к неопределенному поведению.

Наконец, используйте список инициализации:

список
pump::pump() : 
portNumber(L"com9") 
{} 

Инициализация заключается в инициализации, конструктор должен закончить строительство. (Кроме того, this-> является уродливым почти для всех людей C++, это не приятно и излишне.)

+0

Что делать, если определение portNumber не может быть изменено, поскольку оно является частью стороннего кода? Кажется, я не могу заставить предупреждение уйти все, что я пытаюсь, поскольку я не знаю, как сообщить компилятору не делать буквального. –

+0

@MikeVersteeg: Если вы не можете изменить код, ваш единственный вариант - попытаться подавить предупреждение. AFAIK, большинство компиляторов имеют способы отключения и повторного включения предупреждений с помощью прагмы - вы можете отключить предупреждения до '# include' и повторно использовать после. – GManNickG

+0

Спасибо, но это невозможно для компиляторов C++ 11 (по крайней мере, не для меня). Мне удалось обойти проблему, динамически создавая строку и используя ее. Многому научился с этой должности. –

2

Используйте const wchar_t*, чтобы указать на литерал.

Причина, по которой существует преобразование, заключается в том, что она была действительной с ранних версий C, чтобы присваивать строковый литерал указателю не const [*]. Причина, по которой она устарела, заключается в том, что она неверна для изменения литерала, и рискованно использовать указатель не const, чтобы ссылаться на то, что не должно быть изменено.

[*] C первоначально не было const. Когда было добавлено const, очевидно, что оно должно применяться к строковым литералам, но там уже был код, написанный до const, который сломался бы, если бы внезапно вам пришлось посыпать const всюду. Мы все еще платим сегодня за это нарушение языка.Поскольку это C++, который вы используете, это не было даже переломным для этого языка.

+0

Одна из вещей, которые разрушают большинство C++, - это совместимость с C назад даже в самых идиотических вариантах (включая стандартную библиотеку C). –

1

По-видимому, portNumber является wchar_t * (не константа), правильно? Если это так:

  • первый неправильно, поскольку строковые литералы только для чтения (они константные указатели на массив полукокса обычно хранится в таблице строк исполняемого файла, который отображается в памяти где-то, часто на странице только для чтения).
    Углевое, неявное преобразование в неконстантный char s/wchar_t s одобрено, IIRC, для обеспечения совместимости со старым кодом, записанным, когда const даже не существовал; к сожалению, это позволяло многим идиотам, которые не знают, что const correctness означает уйти с написанием кода, который задает неконстантные указатели, даже если константные указатели будут правильным выбором.

  • Второе неверно, потому что вы делаете portNumber, указываете на переменную, выделенную в стеке, которая удаляется при возврате конструктора. После возврата конструктора указатель, сохраненный в portNumber, указывает на случайный мусор.

Правильный подход заключается в объявлении portNumber, как const wchar_t * если это не должны быть изменены. Если вместо этого это делает необходимо изменить в течение всего жизненного цикла класса, как правило, наилучшим подходом является избежание строк в стиле C, и просто введите std::wstring, который позаботится обо всех бухгалтерских книгах, связанных с строка.

+0

Спасибо за информацию. В этом случае номер порта может быть изменен динамически (из выпадающего меню), потому что насос может не всегда находиться на com9. Причина, по которой я использую указатель wchar_t вообще, заключается в том, что он необходим в качестве аргумента в функции CreateFile(). Я увижу, принимает ли он std :: wstring. – Zac

+1

Он не принимает wstring, но wstring (как любая строка, построенная на std :: basic_string) предоставляет метод c_str(), который возвращает const wchar_t *, чтобы позволить функциям C получить доступ к его контенту. –