Программирование >>  Поддержка объектно-ориентированного программирования 

1 ... 9 10 11 [ 12 ] 13 14 15 ... 120


программист.

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

С++ проектировался для поддержки того принципа, что всякая программа есть модель некоторых существующих в реальности понятий, а класс является конкретным представлением понятия, взятого из области приложения ($$12.2). Поэтому классы пронизывают всю программу на С++, и налагаются жесткие требования на гибкость понятия класса, компактность объектов класса и эффективность их использования. Если работать с классами будет неудобно или слишком накладно, то они просто не будут использоваться, и программы выродятся в программы на лучшем С . Значит пользователь не сумеет насладиться теми возможностями, ради которых, собственно, и создавался язык.



ГЛАВА 2. ОПИСАНИЯ И КОНСТАНТЫ

Совершенство достижимо только в момент краха .

(С.Н. Паркинсон)

В данной главе описаны основные типы (char, int, float и т.д.) и способы построения на их основе новых типов (функций, векторов, указателей и т.д.). Описание вводит в программу имя, указав его тип и, возможно, начальное значение. В этой главе вводятся такие понятия, как описание и определение, типы, область видимости имен, время жизни объектов. Даются обозначения литеральных констант С++ и способы задания символических констант. Приводятся примеры, которые просто демонстрируют возможности языка. Более осмысленные примеры, иллюстрирующие возможности выражений и операторов языка С++, будут приведены в следующей главе. В этой главе лишь упоминаются средства для определения пользовательских типов и операций над ними. Они обсуждаются в главах 5 и 7.

2.1 ОПИСАНИЯ

Имя (идентификатор) следует описать прежде, чем оно будет использоваться в программе на С++. Это означает, что нужно указать его тип, чтобы транслятор знал, к какого вида объектам относится имя. Ниже приведены несколько примеров, иллюстрирующих все разнообразие описаний:

char ch; int count = 1; char* name = Njal ; struct complex { float re, im; }; complex cvar;

extern complex sqrt(complex); extern int error number; typedef complex point;

float real(complex* p) { return p->re; }; const double pi = 3.1415926535897932385; struct user;

template<class T> abs(T a) { return a<0 ? -a : a; } enum beer { Carlsberg, Tuborg, Thor };

Из этих примеров видно, что роль описаний не сводится лишь к привязке типа к имени. Большинство указанных описаний одновременно являются определениями, т.е. они создают объект, на который ссылается имя. Для ch, count, name и cvar таким объектом является элемент памяти соответствующего размера. Этот элемент будет использоваться как переменная, и говорят, что для него отведена память. Для real подобным объектом будет заданная функция. Для константы pi объектом будет число 3.1 41 5926535897932385. Для complex объектом будет новый тип. Для point объектом является тип complex, поэтому point становится синонимом complex. Следующие описания уже не являются определениями:

extern complex sqrt(complex); extern int error number; struct user;

Это означает, что объекты, введенные ими, должны быть определены где-то в другом месте программы. Тело функции sqrt должно быть указано в каком-то другом описании. Память для переменной error number типа int должна выделяться в результате другого описания error number. Должно быть и какое-то другое описание типа user, из которого можно понять, что это за тип. В программе на языке С++ должно быть только одно определение каждого имени, но описаний может быть много. Однако все описания должны быть согласованы по типу вводимого в них объекта. Поэтому в приведенном ниже фрагменте содержатся две ошибки:

int count;

int count; ошибка: переопределение

extern int error number;

extern short error number; ошибка: несоответствие типов



локальное x скрывает глобальное x присвоить локальному x

скрывает первое локальное x присвоить второму локальному x

присвоить первому локальному x

int* p = &x; взять адрес глобального x

В больших программах не избежать переопределения имен. К сожалению, человек легко может проглядеть такое переопределение . Возникающие из - за этого ошибки найти непросто , возможно потому, что они достаточно редки. Следовательно, переопределение имен следует свести к минимуму. Если вы обозначаете глобальные переменные или локальные переменные в большой функции такими именами, как i или x, то сами напрашиваетесь на неприятности. Есть возможность с помощью операции разрешения области видимости :: обратиться к скрытому глобальному имени, например:

int x;

void f2()

int x = 1; скрывает глобальное x

::x = 2; присваивание глобальному x

int x;

void f()

int x;

x = 1;

int x;

x = 2;

x = 3;

Зато в следующем фрагменте нет ни одной ошибки (об использовании extern см. #4.2):

extern int error number; extern int error number;

В некоторых описаниях указываются значения объектов, которые они определяют:

struct complex { float re, im; }; typedef complex point;

float real(complex* p) { return p->re }; const double pi = 3.1415926535897932385;

Для типов, функций и констант значение остается неизменным; для данных, не являющихся константами, начальное значение может впоследствии изменяться:

int count = 1; char* name = Bjarne ;

count = 2; name = Marian ;

Из всех определений только следующее не задает значения:

char ch;

Всякое описание, которое задает значение, является определением.

2.1.1 Область видимости

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

глобальное x



1 ... 9 10 11 [ 12 ] 13 14 15 ... 120

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика