Конструкторы в языке C++


1.     Понятие и объявление конструктора класса
2.     Виды конструкторов. Особенности и правила работы с конструкторами.


1.     Понятие и объявление конструктора класса
Конструктор – это метод класса, имя которого совпадает с именем класса. Конструктор вызывается автоматически после выделения памяти для переменной и обеспечивает инициализацию компонент – данных. Конструктор не имеет никакого типа (даже типа void) и не возвращает никакого значения в результате своей работы. Конструктор нельзя вызывать как обычную компонентную функцию в программе. Для класса может быть объявлено несколько конструкторов, различающихся числом и типами параметров. При этом даже если для объектного типа не определено ни одного конструктора, компилятор создает для него конструктор по умолчанию, не использующий параметров, а также конструктор копирования, необходимый в том случае, если переменная объектного типа передается в конструктор как аргумент. В этом случае создаваемый объект будет точной копией аргумента конструктора.


class my_Fun
{
// компоненты-данные
double x;
unsigned size;
public:
// объявление конструктора 1 (с параметрами)
my_Fun (double X=0);

// объявление конструктора 2 (без параметров)
my_Fun(void);
// объявление и описание деструктора
~my_Fun ()
{
cout<<"Destroyed object... "<<endl;
}
// описание конструктора 1
my_Fun::my_Fun (double X)
{
cout<<"Constructor1...."<<endl;
x=X;
}
// описание конструктора 2
my_Fun::my_Fun (void)
{
cout<<"Constructor2..."<<endl;
x=5.0;
}
}

2.     Виды конструкторов. Особенности и правила работы с конструкторами.
Недостатком рассмотренных ранее классов является отсутствие автоматической инициализации создаваемых объектов. Для каждого вновь создаваемого объекта необходимо было вызвать функцию типа set (как для класса complex) либо явным образом присваивать значения данным объекта. Однако для инициализации объектов класса в его определение можно явно включить специальную компонентную функцию, называемую конструктором.
   Конструкторы и деструкторы в С++ вызываются автоматически, что гарантирует правильное создание и разрушение объектов класса.

   Общий вид (синтаксис) объявления конструктора:

class className
{
public:
   className();                     // конструктор по умолчанию
   className(const className &c);   // конструктор копии
   className(<список параметров>);  // конструктор с параметрами
};

   Пример 2:

// Замечание: Здесь только объявление класса без описания объявленных
// функций-параметров

class point
{
protected:
   double x;
   double y;
public:
   point();
   point(double xVal, double yVal);
   point(const point &pt);
   double getX();
   double getY();
   void assign(double xVal, double yVal);
   point& assign(point &pt);
};
int main()
{
  point p1;
  point p2(10, 20);
  point p3(p2);
  p1.assign(p2);
  cout << p1.getX() << " " << p1.getY() << endl;
  cout << p2.getX() << " " << p2.getY() << endl;
  cout << p3.getX() << " " << p3.getY() << endl;
  return 0;
}

   Конструктор копии создает объект класса, копируя при этом данные из существующего объекта класса.

   В С++ имеются следующие особенности и правила работы с конструкторами:

1.     Имя конструктора класса должно совпадать с именем класса.
2.     Нельзя определять тип возвращаемого значения для конструктора, даже тип void.
3.     Класс может иметь несколько конструкторов или не иметь их совсем.
4.     Конструктором по умолчанию является конструктор, не имеющий параметров, или конструктор, у которого все параметры имеют значения по умолчанию.

   Рассмотрим два примера с фрагментами объявления конструкторов.

// класс с конструктором без параметров
class point1
{
protected:
   double x;
   double y;
public:
   point1();
   // другие функции-элементы
};

// конструктор класса имеет параметры со значениями по умолчанию
class point2
{
protected:
   double x;
   double y;
public:
   point2(double xVal = 0, double yVal = 0);
   // другие функции-элементы
};

5.     Конструктор копии создает объект класса на основе существующего объекта.

Например:

class point
{
protected:
   double x;
   double y;
public:
   point();
   point(double xVal = 0, double yVal = 0);
   point(const point &pt);
   // другие функции-элементы
};

6.     Объявление объекта класса, которое может содержать параметры и, в качестве параметра, имя уже существующего объекта, влечет за собой вызов конструктора. Но какой из конструкторов будет использоваться в каждом конкретном случае? Ответ зависит от того, как много конструкторов вы объявили и с какими аргументами вы объявляете объект класса. Например, рассмотрим следующие объявления объектов последней версии класса point:

point p1;                  // применяется конструктор по умолчанию
point p2(1.1, 1.3);   // используется второй по счету конструктор
point p3(p2);           // используется конструктор копии

   Поскольку объект p1 объявляется без параметров, компилятор использует
конструктор по умолчанию. Объект p2 объявляется с двумя вещественными
аргументами, поэтому компилятор вызовет второй конструктор. Объект p3
при объявлении имеет параметром объект p2, поэтому компилятор вызовет
конструктор копии, чтобы создать новый объект из объекта p2.

   ВНИМАНИЕ:

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

Абстрактный тип данных


1.     Понятие абстрактного типа данных.
2.     Чистые виртуальные функции.

1.            Понятие абстрактного типа данных.

Дружественная (friend) функция — это функция, которая, не будучи членом класса, имеет доступ к его приватным членам.
Абстрактные типы данных (abstract data type, в дальнейшем АТД) позволяют создавать программы с использованием высокоуровневых абстракций. За счет применения абстрактных типов данных появляется возможность отделять абстрактные (концептуальные) преобразования, которые программы выполняют над данными, от любого конкретного представления структуры данных и любой конкретной реализации алгоритма.
 Абстрактные типы данных предоставляют в наше распоряжение постоянно расширяющийся набор инструментальных средств, позволяющий приниматься за решение все новых и новых задач.
Абстрактные конструкции более высокого уровня часто создаются на основе более простых конструкций. На всех уровнях действует один и тот же основной принцип: в своих программах надо найти наиболее важные операции и наиболее важные характеристики данных, затем точно определить и те и другие на абстрактном уровне и разработать эффективные конкретные механизмы для их поддержки.
Для разработки нового уровня абстракции потребуется определить абстрактные объекты, с которыми необходимо манипулировать, и операции, которые должны выполняться над ними; мы должны представить данные в некоторой структуре данных и реализовать операции.
Абстрактный тип данных (АТД) — это тип данных (набор значений и совокупность операций для этих значений), доступ к которому осуществляется только через интерфейс.
Class share
{
public:
share() {}
virtual void draw() {}
private:
};
Class circle: public share
{
circle () {}
void draw() {}
private:….
};
Все методы должны функционировать нормально в производных классах, но не в классе share, поскольку невозможно создать экземпляр формы как таковой. Программа должна быть защищена от попытки пользователя создать объект этого класса. Класс share существует только для того, чтобы поддерживать интерфейс, общий для всех производных классов, поэтому об этом типе данных говорят как об абстрактном, или АТД.
Абстрактный тип данных представляет общую концепцию, такую как форма, а не отдельные объекты. В С++ АТД по отношению к другим классам всегда выступает как базовый, для которого невозможно создать функциональный объект абстрактного класса.
2.  Чистые виртуальные функции.
C++ поддерживает создание абстрактных типов данных с чистыми виртуальными функциями. Чистыми виртуальными функциями называются такие, которые инициализируются нулевым значением, например:
virtual void draw()=0;
Класс, содержащий чистые виртуальные функции, является АТД. Невозможно создать объект для класса, который является АТД. Попытка создания объекта для такого класса вызовет сообщение об ошибке во время компиляции. Помещение в класс чистой виртуальной функции будет означать следующее:
- невозможность создания объекта этого класса;
- необходимость замещения чистой виртуальной функции в производном классе.
Любой класс, произведенный от АТД, унаследует от него чистую виртуальную функцию, которую необходимо будет заместить, чтобы получить возможность создавать объекты этого класса.
Чтобы объявить класс как абстрактный тип данных, достаточно добавить в него одну или несколько чистых виртуальных функций. Для этого после объявления функции необходимо добавить =0, например:
Class share
{
Virtual void draw()=0; // чистая виртуальная функция
}
         Выполнение чистых виртуальных функций
Обычно чистые виртуальные функции объявляются в абстрактном базовом классе и не выполняются. Поскольку невозможно создать объект абстрактного базового класса, как правило, нет необходимости и в выполнении чистой виртуальной функции. Класс АТД существует только как объявление интерфейса объектов, создаваемых в производных классах.
         Тем не менее все же иногда возникает необходимость выполнения чистой виртуальной функции. Она может быть вызвана из объекта, произведенного от АТД, например чтобы обеспечить общую функциональность для всех замещенных функций.
         В реальной программе чистая виртуальная функция может содержать достаточно сложный программный код, например создание окна, в котором рисуются все фигуры, выбираемые пользователем.
Подводя итог, перечислим каким целям должен служить абстрактный тип:
  [1] определять некоторое понятие таким образом, что в программе могут сосуществовать для него несколько реализаций;
  [2] применяя виртуальные функции, обеспечивать достаточно высокую степень компактности и эффективности выполнения программы;
  [3] сводить к минимуму зависимость любой реализации от других классов;
  [4] представлять само по себе осмысленное понятие.

Основные понятия языка С#


Содержание:
1.     Основные понятия языка C#
2.     Встроенные типы С# и системные типы
3.     Переменные, константы.

1.     Основные понятия языка С#
Подобен языкам Java, C++ и VB, однако является компонентно-ориентированным и более безопасным
Добавлен ряд новых черт (делегаты, индексаторы, механизм (un)boxing и др.)

Сходство с Java:
объектно-ориентированный (единственное наследование)
интерфейсы
исключения
нити (threads)
пространство имен
сильная (строгая) типизация
сборка мусора
отражение (reflection)
динамическая загрузка кода         
Сходство с С++:
"перегруженные операторы"
арифметические операции с плавающей точкой относятся к небезопасному коду
некоторые особенности синтаксиса

 К числу принципиально важных решений, которые реализованы корпорацией Microsoft в языке программирования C#, можно отнести следующие:
-компонентно-ориентированный подход к программированию (который характерен и для идеологии Microsoft .NET в целом);
-свойства как средство инкапсуляции данных (характерно также в целом для ООП);
-обработка событий (имеются расширения, в том числе в части обработки исключений, в частности, оператор try);
-унифицированная система типизации (соответствует идеологии Microsoft .NET в целом);
-делегаты (delegate – развитие указателя на функцию в языках C и C++);
индексаторы (indexer – операторы индекса для обращения к элементам класса-контейнера);
-перегруженные операторы (развитие ООП);
-оператор foreach (обработка всех элементов классов-коллекций, аналог Visual Basic);
-механизмы boxing и unboxing для преобразования типов;
-атрибуты (средство оперирования метаданными в COM-модели);
-прямоугольные массивы (набор элементов с доступом по номеру индекса и одинаковым количеством столбцов и строк).
2. Встроенные типы С# и системные типы

В С# существует множество встроенных или простых типов. Любой встроенный тип С# -  это псевдоним для системного типа,определённого в пространстве имён System.

Простые типы С# и системные типы
Простой тип С#
Системный тип
Диапазон значений
Описание типа
sbyte
SByte
-128…+128
Число со знаком занимает 1 байт
byte
Byte
0…255
Чісло без знака занимает 1 байт
short
Int16
-32768…32667
Короткое 16 битовое число со знаком (2байта)
ushort
Uint16
0…65535
короткое 16 битовое число без знака
int
Int32
-21474836482147483647
Целое 32 битовое число со знаком
uint
Uint32
0…4294967295
Целое 32 битовое  без знака целое число
long
Uint64
0…18446744073709551615
Знаковое 64-битное целое число(8 байт)
ulong

0…2^64-1
64  битное 8 байтное целое число без знака
char
Char
2 байта для расширенной таблицы кодов символов
Один 16 битовый символ Юникод
float
Single
 -3.40282e+0383.40282e+038
Вещественное число одинарной точности с плавающей запятой, занимающее 32 бита или 4 байта
double
Double
-1.79769e+3081.79769e+308
Вещественное число двойной точности с плавающей запятой, занимает 64 бита либо 8 байт
bool
Boolean
True or False
Логические данные
decimal
Decimal
10^0…10^28
Число фиксированной точности или 12 байт
string
String
Ограниченно системной памятью
Строка символов
object
Object
Практически всё что угодно. Все типы происходят от класса System.Object поэтому объектом является всё

У всех встроенных типов есть значение по умолчанию (0-для числовых, false-bool, nullstring, object; но в методах классов переменные нужно инициализировать).

Системные имена называют также структурами типов значений. Структуры имеют методы. Например Int32 - Parse(string) преобразует строку символов string в число.
3.            Переменные и константы
Константы
 Константа - это объект, значение которого известно еще до начала работы программы. Константы необходимы для оформления наглядных программ, незаменимы при использовании в тексте программы многократно повторяемых значений, удобны в случае необходимости изменения этих значений сразу во всей программе.
 Константа хранит значение, присваиваемое по завершении компиляции программы, и никогда после этого не изменяется. Константы объявляются помощью ключевого слова const; их использование способствует повышению удобочитаемости кода. В языке существует два вида констант:
 неименованные константы (цифры и числа, символы и строки, множества);
 именованные константы;

Неименованные константы

 Неименованные константы не имеют имен, и потому их не нужно описывать. Тип неименованной константы определяется автоматически, по умолчанию:
 любая последовательность цифр (возможно, предваряемая знаком "-" или "+" или разбиваемая одной точкой) воспринимается компилятором как неименованная константа - число (целое или вещественное);
 любая последовательность символов, заключенная в апострофы, воспринимается как неименованная константа - строка;
 любая последовательность целых чисел, либо символов через запятую, обрамленная квадратными скобками, воспринимается как неименованная константа - множество.

 Кроме того, существуют две специальные константы true и false, относящиеся к логическому типу данных. Примерами использования неименованных констант могут послужить следующие операторы:
a = -10;
b = 12.075 + х;
c = 'z';
d = "abc" + string44;

Именованные константы

 Именованные константы, как следует из их названия, должны иметь имя. Стало быть, эти имена необходимо сообщить компилятору, то есть описать в специальном разделе const.

 Если не указывать тип константы, то по ее внешнему виду компилятор сам определит, к какому (базовому) типу ее отнести. Любую уже описанную константу можно использовать при объявлении других констант, переменных и типов данных. Вот несколько примеров описания нетипизированных именованных констант:
const int speedLimit = 55;
const double pi = 3.14159265358979323846264338327950;
Переменные
 В C# переменные объявляются с определенным типом данных и надписью. Если ранее вам приходилось работать со слабо типизированными языками, например JScript, вы привыкли использовать один тип "var" для всех переменных, то в C# необходимо указать тип переменной: int, float, byte, short или другой из более чем 20 различных типов данных. Тип указывает, помимо всего прочего, точный объем памяти, который следует выделить для хранения значения при выполнении приложения. При преобразовании переменной из одного типа в другой язык C# следует определенным правилам. Пример:
int i;
int answer = 42;
string greeting = "Hello, World!";
double bigNumber = 1e100;
Console.WriteLine("{0} {1} {2}", answer, greeting, bigNumber);

Идентификаторы

 Имена операторов, переменных, констант, типов величин, имя самой программы назначаются программистом и называются идентификаторами. Существуют правила, которым должны отвечать все идентификаторы:
 идентификатор должен быть уникальным, то есть одним и тем же именем разные объекты не могут быть названы;
 идентификатор имеет ограничение по длине (зависит от конкретной реализации языка на компьютере);
 идентификатор может состоять только из символов латинского алфавита, цифр и знака подчеркивания ("_"), регистр букв имеет значение;
 идентификатор не может начинаться с цифры.
//допустимые имена
x  ,  s5  ,  Ax6 ,  D_f  , _Fm5 , xM_5 , _128

 Имена - это идентификаторы. Любая случайным образом составленная последовательность букв, цифр и знаков подчёркивания с точки зрения грамматики языка идеально подходит на роль имени любого объекта, если только она начинающаяся с буквы. Фрагмент программы, содержащий подобную переменную, будет синтаксически безупречен.

 И всё же имеет смысл воспользоваться дополнительной возможностью облегчить восприятие и понимание последовательностей операторов. Для этого достаточно закодировать с помощью имён содержательную информацию.

 Желательно создавать составные осмысленные имена. При создании подобных имён в одно слово можно "втиснуть" предложение, которое в доступной форме представит информацию о типе объекта, его назначении и особенностях использования.

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