Студопедия

КАТЕГОРИИ:

АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Преобразование неполиморфных типов static_cast




Формат операции:

static_cast <type-id> (exp)

 

Преобразует exp в тип type-id на основе исключительно тех типов, которые присутствуют в выражении. На этапе выполнения никакой контроль типов не производится.

Операция static_cast может быть использована для преобразования указателя на базовый класс в указатель на производный класс. Такие преобразования не всегда безопасны.

Преимущественно эта операция используется для преобразования таких числовых данных, как перечисления, в целочисленный тип или целых в вещественные. Операция static_cast менее безопасна по сравнению с dynamic_cast, поскольку static_cast не контролируется на этапе выполнения, в то время как при выполнении dynamic_cast это делается. В то время как dynamic_cast вызовет ошибку при преобразовании неоднозначных указателей, операция static_cast выполнится без ошибки, что опасно. Пример:

// static_cast_Operator.cpp

// compile with: /LD

class B {};

class D : public B {};

 

void f(B* pb, D* pd)

{

D* pd2 = static_cast<D*>(pb); // опасно, так как pb может указывать именно на B

B* pb2 = static_cast<B*>(pd); // безопасное преобразование

}

 

В противоположность dynamic_cast, при выполнении static_cast не выполняется проверка указателя на этапе выполнения. Это значит, что, к примеру, вызов функции класса D, а не В, вызовет ошибку “access violation”.

Еще один пример:

// static_cast_Operator_2.cpp

// compile with: /LD /GR

class B {

public:

virtual void Test(){}

};

class D : public B {};

 

void f(B* pb)

{

D* pd1 = dynamic_cast<D*>(pb);

D* pd2 = static_cast<D*>(pb);

}

 

Если pb действительно указывает на объект типа D, то pd1 и pd2 будут иметь одно и то же значение. Они также будут иметь одинаковое значение, если pb == 0.

Если же pb указывает на объект типа B, а не на завершенный класс D, то dynamic_cast вернет значение 0. Напротив, static_cast зависит от убежденности программиста в том, что pb указывает на объект типа D и просто вернет указатель на предполагаемый объект типа D.

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

Такое поведение операции свойственно не только применительно к классам. Например, static_cast может быть использована для преобразования int в char. Однако, результирующий тип char может не иметь достаточного количества битов для сохранения значения int. Пример для иллюстрации:

// static_cast_Operator_3.cpp

// compile with: /LD /GR

typedef unsigned char BYTE;

 

void f()

{

char ch;

int i = 65;

float f = 2.5;

double dbl;

ch = static_cast<char>(i); // int to char

dbl = static_cast<double>(f); // float to double

i = static_cast<BYTE>(ch);

}

 

 

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

Операция static_cast конвертирует нулевой указатель в нулевой указаетль результирующего типа.

Любое значение может быть конвертировано к типу void с помощью static_cast. Результирующий тип void может включать атрибуты const, volatile и __unaligned.

Операция static_cast не может отменить действие атрибутов const, volatile или __unaligned. См. операцию const_cast.

 

Преобразование reinterpret_cast

Преобразует любой указатель в указатель другого типа:

reinterpret_cast <type_id > (exp)

 

Эта операция позволяет конвертировать любой интегральный тип в любой указатель и наоборот. The reinterpret_cast operator also allows any integral type to be converted into any pointer type and vice versa. Неправильное использование операции reinterpret_cast может легко стать небезопасным.

Операция reinterpret_cast может быть использована для таких преобразований, как char* в int* или One_class * в Unrelated_class*, которые по своей сути небезопасны.

Результат преобразования reinterpret_cast не может быть безопасно использован, если обратное преобразование не позволяет вернуться к первоначальному значению. Другие преобразования, в лучшем случае, являются непереносимыми.

Операция reinterpret_cast не может отменить действие атрибутов const, volatile или __unaligned.

Операция reinterpret_cast преобразует нулевой указатель в нулевой указатель результирующего типа.

Примером практического использования операции может служить хэш-функция, которая отображает значение в индекс таким образом, что два разных значения редко получают один и тот же индекс, например:

// expre_reinterpret_cast_Operator.cpp

// compile with: /EHsc

// генерирует и возвращает хэш-код по адресу

unsigned short Hash( void *p )

{

unsigned int val = reinterpret_cast<unsigned int>( p );

return ( unsigned short )( val ^ (val >> 16));

}

 

int main()

{

int a[20];

for ( int i = 0; i < 20; i++ )

cout << Hash( a + i ) << endl;

}

 

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

 

 



Соглашения об именах


Хорошая реклама венгерской нотации содержится в работе К.Х.Паппас, У.Х.Мюррей «Отладка в С++» (есть .pdf). Там же есть и другая полезная информация, касающаяся соглашений об именах.

 

Имена типов.

В Windows SDK и MFC используются такие имена типов:

BOOL булевский тип
BSTR 32-разрядный указатель на символ
BYTE 8-разрядное беззнаковое целое
COLORREF 32-разрядное значение, используемое как значение цвета
DWORD 32-разрядное беззнаковое целое, сегмент или смещение адреса
LONG 32-разрядное знаковое целое
LPARAM 32-разрядное значение, передаваемое как параметр оконной процедуре или callback-функции
LPCSTR 32-разрядный указатель на константную строку символов
LPSTR 32-разрядный указатель на строку символов
LPCTSTR 32-разрядный указатель на константную строку символов, совместимую с Unicode и DBCS
LPTSTR 32-разрядный указатель на строку символов, совместимую с Unicode и DBCS
LPVOID 32-разрядный нетипизированный указатель
LRESULT 32-разрядное значение, возвращаемое оконной процедурой или callback-функцией
UINT 16-разрядное беззнаковое целое в версиях Windows 3.0 и 3.1; 32-разрядное беззнаковое целое в Win32
WNDPROC 32-разрядный указатель на оконную процедуру
WORD 16-разрядное беззнаковое целое
WPARAM Значение, передаваемое как параметр оконной процедуре или callback-функции: 16-разрядное в версияхWindows 3.0 и 3.1 и 32-разрядное – в Win32.

 

В MFC используются также такие типы:

POSITION Значение, используемое для указания позиции элемента в коллекции, используемой классами MFC
LPCRECT 32-разрядный указатель на константную структуру RECT

 

Имена переменных и функций.

Фирма Microsoft использует сама и рекомендует другим разработчикам руководствоваться соглашениями об именах, известных также как «венгерская» нотация. Для функций используются имена, построенные из глаголов и существительных, причем первые буквы этих слов рекомендуется делать заглавными.

Для имен переменных Microsoft предлагает более сложную систему, предусматривающую указание в качестве префикса типа данных. Префикс рекомендуется составлять из строчных букв, а собственно имя начинать с заглавной буквы. Типы префиксов представлены в нижеследующей таблице. Откровенно говоря, использование префиксов, обозначающих тип данных, спорно и не всегда адекватно. Большинство Windows-программистов прибегают к такой системе именования, но Вы в своих программах можете поступать по своему усмотрению.

 

 

Префикс Тип данных
b Булевский bool
с Символ char
s Строка ( char* или CString ).
dw Длинное беззнаковое целое (DWORD – 32 бита)
f 16-битный флаг (битовая карта).
fn Функция.
h Дескриптор (handle).
l Длинное целое (long).
i Целое int (индекс)
Длинный указатель (long pointer).
n Целое int (количество).
р Указатель (pointer).
pt Точка (два 32-битных целых).
w Целое без знака (WORD, 16 бит).
sz Указатель на строку с завершающим 0
Ipsz Длинный указатель на строку с завершающим 0.
rgb Длинное целое, содержащее цветовую комбинацию RGB.

 

Другие гласные и негласные соглашения.

В библиотеке MFC и приложениях, разрабатываемых с ее помощью, принято имена классов начинать с большой буквы C: CString, CDialog и т.п.

Имена констант, перечислений и макросов в библиотеках принято, как правило, задавать заглавными буквами: NULL или IDCANCEL (значения заданы с помощью директивы препроцессора define), enum { IDD = IDD_ABOUTBOX }, TRACE (макрос).

Имена член данных классов принято начинать с префикса m_, например, m_pDocument (член указатель на документ).

 

Соглашения об именовании библиотек MFC DLL и LIB. (См. также в MSDN указатель «Conventions»)

Имена библиотек MFC (.dll и .lib) назначаются в соответствии с приведенными ниже соглашениями, что помогает сориентироваться в том, какие библиотеки и для какой цели используются в каждом конкретном случае.

Разделяемые библиотеки (shared MFC DLL в отличие от статически связываемых Static-Link Regular DLL) именуются в соответствии с шаблоном

MFC[O|D|N]x0[U][D].DLL

где x – номер версии MFC.

 

Библиотеки импорта .lib (import libraries), которые используются для компоновки приложений или DLL-расширений (extension DLLs), имеют те же имена, но расширение .lib вместо .dll. 

 

Именование разделяемых библиотек MFC DLL

DLL Описание
MFCx0.DLL версия ANSI Release
MFCx0U.DLL версия Unicode Release (символ U)
MFCx0D.DLL версия ANSI Debug (символ D)
MFCx0UD.DLL версия Unicode Debug (символы UD)
MFCOx0D.DLL версия ANSI Debug для технологии ActiveX (символ O)
MFCOx0UD.DLL версия Unicode Debug для технологии ActiveX (символы O, U и D)
MFCDx0D.DLL версия ANSI Debug для баз данных (символ D в четвертой позиции)
MFCDx0UD.DLL версия Unicode Debug для баз данных
MFCNx0D.DLL версия ANSI Debug для сетей (сокетов) (символ N)
MFCNx0UD.DLL версия Unicode Debug для сетей (сокетов)
MFCSx0.LIB версия Release для статически компонуемого кода (символ S в четвертой позиции)
MFCSx0D.LIB версия Debug для статически компонуемого кода

 

Примечания к таблице.

Release – окончательная версия, Debug – отладочная.

Библиотеки DLL, содержащие элементы управления ActiveX, обычно имеют тип .ocx.

Библиотеки импорта MFCSx0[D].LIB используются в связке с библиотеками MFC DLL.

Если Вы динамически компонуете разделяемые библиотеки MFC DLL с приложениями или DLL-расширениями, Вы должны распространять вместе с приложением библиотеки MFCx0.DLL или Unicode-версии MFCx0U.DLL.

Retail-версии библиотек MFCx0.DLL и MFCx0U.DLL содержат поддержку технологии Active, баз данных и сетей в одной единственной DLL, в то время как Debug-версии используют разные библиотеки для этих функциональных областей.

.

Если Вы статически компонуете свою DLL с MFC, Вы должны компоновать ее с одной из статических библиотек MFC. Эти библиотеки именуются в соответствии с шаблоном [N|U]AFXCW[D].LIB, описанным в следующей таблице.

 

Соглашения об именах статически компонуемых библиотек (Static-Link Regular DLL)

DLL Description
NAFXCW.LIB MFC Static Link Library, версия Release
NAFXCWD.LIB MFC Static Link Library, версия Debug
UAFXCW.LIB MFC Static Link Library версия Release с поддержкой Unicode
UAFXCWD.LIB MFC Static Link Library версия Debug с поддержкой Unicode

 

Примечание. В версиях MFC до 4-ой использовались специальные варианты библиотек с именами в формате [N|U]AFXDW[D].LIB. Эти библиотеки сейчас не используются и вместо них надо применять версии, приведенные в таблице.

Полный список библиотек Visual C++, которые могут распространяться с приложением, приведен в файле REDISTRB.WRI на компакт-диске с Visual C++. В MSDN сведения о библиотеках, которые необходимо распространять вместе с приложением, можно найти в разделе «Categories of Redistributable Files».

 

 



Пространства имен

 

Пространство имен представляет собой механизм логического группирования объявлений, которые можно объединить по какому-либо критерию общности. Пространства имен являются одним из средств решения проблемы конфликта имен, которая имеет место быть в большой программе. Объявление пространства имен (namespace declaration):

Namespace MyNameSpace

{

int iNumber=0;

int Func(float);

void Hello(){cout<<”Hello!”<<endl;}

}










Последнее изменение этой страницы: 2018-04-12; просмотров: 353.

stydopedya.ru не претендует на авторское право материалов, которые вылажены, но предоставляет бесплатный доступ к ним. В случае нарушения авторского права или персональных данных напишите сюда...