- •1.1. Что такое программа и как она выглядит?
- •1.2. Комментарии
- •1.3. Зарезервированные слова и типы данных
- •1.4. Объявление переменных
- •1.5. Операции и выражения
- •1.6. Ввод и вывод
- •1.7. Переменные и константы
- •1.8 Логические операторы
- •1.9. Управляющие операторы
- •1.10. Операторы циклов
- •1.11. Операторы перехода
- •2. Функции
- •2.1. Передача параметров
- •2.2. Библиотечные функции
- •2.3. Локальные и глобальные переменные
- •Объявления функций
- •Время жизни и область видимости программных объектов
- •Int local_var; /* по умолчанию auto */
- •2.4. Перегрузка
- •3. Массивы
- •4. Структуры
- •Int numberPeriod; //число переодов начисления процентов
- •Int page; //Количество страниц
- •Void print(); /*Внимание, записывается только прототип функции */
- •Int yearBorn; //год рождения
- •Int yearBorn; //год рождения
- •4.1. Демонстрационные программы
- •Int done;/*переменная, которая информирует о конце списка файлов */
- •6. Объединения
- •Info;//Обявление переменной типа объединение
- •Info;//Обявление переменной типа объединение
- •7. Объектно-ориентированное программирование
- •7.1. Классы и объекты
- •Демонстрационные программы
- •Результат работы программы
- •7.2. Конструкторы и деструкторы
- •Конструктор копирования
- •7.5. Наследование
- •7.3. Создание объектов и обращение к членам объекта
- •8. Абстрактные типы данных
- •9. Пространство имен
- •Void greeting();/*это пространство имен содержит функцию с тем же именем*/
- •Void big_greeting(); /*эта функция не попадает ни в одно из созданных подпространств,т.Е. Принадлежит пространству имен std */
- •//Определение функций
- •Void big_greeting() /* определение данной функции не принадлежит ни одному из созданных пространств имен, следовательно дальнейший код помещается в глобальное пространство имен */
- •10. Строки
- •4.3 Демонстрационные программы
- •4.10. Класс string
- •Класс AnsiString
- •Класс AnsiString
- •Класс Set
- •4.9. Перегрузка операторов
- •Использование "умных" указателей
- •4.8. Полиморфизм
- •Главное меню — компонент MainMenu
- •Диалоги
- •Файлы и потоки
- •Ввод-вывод в файл
- •Ifstream inStream; //Объявление входного потока
- •InStream.Open("character.Dat"); /*присоединение файла к входному потоку */
- •InStream.Close(); //закрытие входного потока
- •If(!out){ //при неудачной попытке
- •If(in.Fail()){ //поток не создан, то сообщение и выход
- •Управление потоком ввода-вывода
- •5.2. Ввод имен файлов
- •5.3. Манипуляторы
- •5. Указатели
- •5.1.Типы указателей и операции с указателями
- •Адресная арифметика
- •Сравнение указателей
- •Преобразование типа указателя
- •Указатель void
- •5.2. Динамические массивы
- •Int array[10]; //объявляется массив с именем array
- •Int a[10]; //объявляется массив с именем a
- •Int *array1; //указатель типа int с именем array1
- •Int *array[5];/*массив с именем array, его элементы указатели*/
- •Int (*point)[4][5]; /*объявление указателя на двумерный массив без имени */
- •Использование указателей в функциях и указатели на функции
- •Указатель классов
- •Шаблоны
- •Шаблоны функций
- •Void Swap (t& X, t& y) /* к моменту обращения тип т будет известен и заменен, например, на int */
- •Void sort(t array[], int maxIndex){ /*передали массив и его размер */
- •6.2. Шаблоны классов
- •6.3 Демонстрационные программы
- •7.1 Обработка исключений
- •Исключения и их стандартная обработка
- •Базовый класс исключений vcl Exception
- •Упражнения
- •Обработка исключительных ситуаций, возбуждаемых оператором new
- •Исходные файлы и объявление переменных
- •Связаные списки
- •Void newHead( //прототип функции создающей узел
- •Void newHead(//прототип функции создания узла
- •Поиск в связанных списках
- •Void newHead(PtrNode& head, //адрес головного узла
- •Директивы препроцессора.
- •Структура файла проекта
- •Структура make-файла
- •Структура модуля
- •Структура h-файла
- •Файл формы
- •Особенности программирования под Windows.
- •Функция WinMain
- •Создание проекта Win32Application.
- •Библиотека mfc.
- •Создаем код
- •Шпаргалка
- •Структура файла проекта
- •Структура make-файла
- •Структура модуля
- •Структура h-файла
- •Файл формы
- •Файл проекта
- •Введение
- •Свойства компонентов
- •События
- •Менеджер проектов
- •Пример: создание простейшего приложения
- •Графика Внедрение картинок
- •Редактор изображений
- •Классы для хранения графических объектов.
- •If (SelectDirectory( //Компонент библиотеки
- •Методы создания собственной графики. Рисование по пикселам
- •Int px, py; //координаты пикселей
- •Рисование с помощью пера
- •Int px, py; //координаты пикселей
- •Рисование кистью
- •Мультимедиа и анимация Общие сведения о звуковых и видеофайлах
- •Способы воспроизведения звуков
- •Создание мультфильма
- •Воспроизведение немых видео клипов — компонент Animate
- •Проигрыватель MediaPlayer
- •Процессы, потоки, распределенные приложения
- •If include "uOverlayl.H" // включение головного файла приложения
- •Функция CreateProcess
- •490 _ Глава 7
- •7.8.4 Элементы ActiveX
- •492 Глава 7
- •494 Глава 7
- •7.9 Компоненты-серверы сом
- •496 Глава 7
- •7.9.2 Свойства и методы сервера Word
- •500 Глава 7
- •Заключение
- •Что такое ansi?
- •Почему вместо русских букв в консольном приложении выводится мусор? Автор: Алексей Кирюшкин Версия текста: 1.0
- •Раздел I.2Выход 1
- •Раздел I.3Выход 2
- •Раздел I.4Выход 3
- •Раздел I.5Выход 4
- •(A)Потоки
- •(C)Ввод-вывод файлов
- •Выбор компонентов для групповых операций
- •Установка разделяемых свойств компонентов
- •Изменение размера компонентов
- •Выравнивание компонентов
- •Пример: Создание текстового редактора Проектирование формы приложения
- •Создание обработчиков событий
- •Создание меню
Класс Set
Set - это шаблон, определенный в заголовке sysset.h:
tempiate
class _declspec(delphireturn) Set;
При объявлении конкретного класса нужно задать следующие параметры: тип элементов (обычто целый, символьный или перечисление), минимальное значение, которое может содержать множество (должно быть не меньше 0), и максимальное значение, которое может входить в множество (должно быть не больше 255). Вот примеры:
Set a5et0f32;
typedef Set SetOfUppercase;
Перегруженный конструктор создает либо пустое множество, либо копию существующего множества того же типа.
Множества можно складывать, умножать (объединение и пересечение) и вычитать (пересечение c дополнением). Операции " и " соответственно вводят или удаляют элемент из множества. Эти же операции могут использоваться для извлечения и передачи множеств в поток (в виде последовательностей нулей и единиц), если перед sysset.h включается заголовок iostream или директива
#define VCL_IOSTREAM
Множества Set имеют два метода:
Sets _fastcall Clear (); Удаляет из множества все элементы.
boo1 _fastcall Contains(const T el) const; Возвращает true, если множество содержит указанный элемент.
/* Compile with bcc32 famille.cpp vcl.lib ole2w32.lib */
#include <vcl.h>
#include <stdio.h>
class Famille //Класс фамилия
{
private:
AnsiString FNames[10]; //Массив фамилий
AnsiString GetName(int Index); //прототипы функций
void SetName(int, AnsiString);
public:
//Создаем массив имен
__property AnsiString Names[int Index] = {read=GetName, write=SetName}; //массив читает номер и пишет имя
Famille(){} //пустой конструктор
~Famille(){}
};
AnsiString Famille::GetName(int i)
{return FNames[i];
}
void Famille::SetName(int i,const AnsiString s)
{FNames[i]=s;
}
int main()
{
Famille C;
C.Names[0]="Steve"; //calls Famille::SetName()
C.Names[1]="Amy";
C.Names[2]="Sarah";
C.Names[3]="Andrew";
for (int i = 0; i <= 3; i++)
{
//calls Famille::GetName()
puts(C.Names[i].c_str()); //вывод на экран
}
}
4.9. Перегрузка операторов
В С++ кроме перегрузки функций есть возможность перегрузки операторов. Напомним, что перегрузка это не замена одних свойств на другие, а добавление новых свойств. В данном случае новые свойства появляются у операторов.
Необходимость в создании перегруженных опереаторов обычно возникает после создания новых типов переменных. Например, представьте себе, что объектами некого класса являются геометрические фигуры. Пусть человек, который использует эти объекты, из отдельных фигур хочет создать картину. По-существу картина это новая фигура, которая является объектом того же класса, но с другой стороны она является суммой отдельных фигур. Поэтому естественно перегрузить знак +, т.е. сделать его пригодным для суммирования геометрических фигур. Это позволит создавать картины из готовых элементов.
Перегруженная операция представляет собой функцию со специальным именем, в которой описывается переопределение оператора. Необходимость в перегрузке операторов обычно возникает тогда, когда от оператора требуется чтобы он работал с классами также как с числами. Например, оператор + можно использовать для того, чтобы указать, что строки нужно соединить вместе. Рассмотрим как можно сделать перегрузку операторов.
Пусть @ некоторый оператор языка, кроме следующих:
. – доступ к элементу класса (точка);
.* - доступ к указателю (точка со зведочкой);
:: - разрешение области видимости (двойное двоеточие);
?: - трехместная условная операция, (вопросительный знак с двоеточием, то же самое, что if - else);
# - указание препроцессору.
Тогда достаточно определить функцию с именем operator@ требуемым числом и типом аргументов, так, чтобы эта функция выполняла необходимые действия. То есть
Тип_результата operator @ (список_параметров)
{
//тело функции
}
Но в том случае, когда перегрузка производится в классе, т.е. функция-оператор является членом класса перегрузка имеет вид
Тип_результата имя_класса::operator @ (список_параметров)
{
//тело функции
}
То есть перегрузка оператора это построение функции с именем из специальных символов без передачи аргументов в явном виде. Перегрузка осуществляется с помощью кдючевого слова operator. Хотя функцию operator @ (список_параметров) можно использовать как обычную функцию. Оба способа будут показана в примере, который мы рассмотрим чуть позже.
При перегрузке операторов следует руководствоваться правилом:
Перегрузка не может изменять старшинство и ассоциативность операций;
Нельзя изменять число операндов операций;
операция присваивания = может быть использована с любым классом без явной перегрузки.
По крайней мере один аргумент перегруженного оператора должен принадлежать типу который является классом
Невозможно создать новый оператор. Все, что можно сделать, - это перегузить существующий оператор.
Нельзя изменять значение оператора по отношению к встроенным типам, т.е int, double, bul, и т.д.
Функция-операция (т.е. operator @ ) должна быть либо членом класса (структуры), либо воспринимать один или несколько аргументов, имеющих тип класса или структуры.
Рассмотрим пример перегрузки операторов в задаче сложения комплексных чисел. В программе перегружены операторы + и += . Причем показано, что перегрузка возможна для выбранных типов переменных.
//Сложение 2-х комплексных чисел
#include <iostream>
#include <windows>
using namespace std;
struct Complex{double real, imag;}; /* Объявление структуры в которой хранятся вещественная и мнимая части комлексного числа */
//--------------------------------------------------------
//Перегрузка оператора +
/*объявляем функцию аргументами которой являются адреса 2-х структур типа Complex*/
Complex operator+(Complex &a, Complex &b){
Complex c;
c.real=a.real+b.real;
c.imag=a.imag+b.imag;
return c;}
//--------------------------------------------------------
//Перегрузка унарного оператора += для комплексных чисел
void operator +=(Complex &a, Complex &b){
/*эта запись говорит о том, что если встретится инструкция a+=b то нужно сделать следующее */
a.real=a.real+b.real;
a.imag=a.imag+b.imag;
}
//------------------------------------------------------
/* Перегрузка унарного оператора += для действительных чисел типа double */
void operator +=(Complex &a, double b){
a.real +=b;
}
//-------------------------------------------------------
//определение функции для вывода комплексных чисел
void showComplex (const Complex &x){
if(x.imag>=0)cout<<x.real<<"+j"<<x.imag<<endl;
else cout<<x.real<<"-j"<<-x.imag<<endl;
}
//--------------------------------------------------------
int main(){
Complex x,y,z1,z2;
x.real=20; x.imag=40;
y.real=30; y.imag=50;
SetConsoleOutputCP(1251);
cout<<"Первое число:"; showComplex(x); //Вывод числа x
cout<<"Второе число:"; showComplex(y); //Вывод числа y
z1=operator+(x,y); //здесь перегрузка используется как функция
cout<<"Определение суммы с помощью функции:"; showComplex(z1);
z2=x+y; //перегруженный оператор используется в операции
cout<<"Определение суммы с помошью оператора:"; showComplex(z2);
z1 +=x; //то же, что operator+=(z1,x);
cout<<"Если добавить первое число к сумме, то получится:"; showComplex(z1);
z2 +=30.0; //то же, что operator+=(z2,30.0);
cout<<"Если добавить число 30 к сумме, то получится:"; showComplex(z2);
int i; cin>>i;
return 0;
}
Вот результат работы программы
В этой программе одна и таже функция перегрузки
Complex operator+(const Complex &a,const Complex &b)
используется по-разному. Один раз как обычная функция, которая вызывается из функции main() с помощью ее имени с указанием аргументов
z1=operator+(x,y);
Второй раз как перегруженный оператор
z2=x+y;
Вызов функции в качестве оператора сложения не вызывает никаких трудностей. Напротив, второй вариант, вероятно, не совсем понятен. Сделаем некоторые пояснения. Встретив знак + для небазового типа Complex компилятор проверяет, не является ли этот оператор перегруженным. С этой целью он ищет функцию, у которой имя содержит ключевое слово operator и указанный знак операции. Если эта функция найдена, то он проверяет соответствие её параметров числу и типам операндов. После этого обеспечивает выполнение написанного кода.
В качестве примера перегрузки в классе рассмотрим перегрузку опрератора массива или, лучше сказать, оператора работы с индексами [ ]. В качестве примера рассмотрим класс предназначенный для хранения строки и числа. Чтобы привлечь ваше внимание пусть это будет имя шпиона и его поядковый идентификационный номер (ПИН). Программа подготовлена для случая когда агент по имени Bond забыл свой номер. Введя свое имя, а точнее фамилию он узнает номер.
#include <iostream>
#include <string>
using namespace std;
const int MAX_LEN=100;
/* Класс для хранения имени шпиона и его ПИНа
* имя хранится в массиве strcpy, а ПИН в переменной типа
* int decoderKey */
class SecretInfo{
int decoderKey;
char codeName[MAX_LEN];
public:
SecretInfo(char *spyName, int spyKey); /*Объявляем конструктор
* с двумя аргументами */
int operator [](const char *spyName); //Перегрузка [] вклассе
}; //Конец класса
//Определение конструктора
/* Данный конструктор осуществляет перезапись аргументов
* в переменные объявленные в классе */
SecretInfo::SecretInfo(char *spyName, int spyKey){
strcpy(codeName, spyName); /* встроенная функция strcpy
* копирует вторую строку в первую */
decoderKey=spyKey;
}
/* Определение перегружаемого оператора */
int SecretInfo::operator[](const char *spyName){
if(!strcmp(codeName, spyName)) /* strcmp функция сравнения строк
* возвращает 0 если строки совпадают
* следует напомнить, что в языке С
* вместо false используется ноль*/
return decoderKey;
else
return 0;
} //конец функции-оператора
/*теперь оператор [] означает ПИН агента*/
//===========================================
int main(void){
SecretInfo agent("Bond",7);
char temp[MAX_LEN];
cout<<"Input Your code name:";
cin>>temp;
if(agent[temp])
cout<<"Your Kode Name"<<agent.operator [](temp);
else
cout<<"Sorry Bond! False Name Code"<<endl;
char z;
cin>>z;
return 0;
}
Пример
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#define EOS -1 //Конец строки(возвращаеться функцией get_word)
using namespace std;
class dict_el{ //Элемент словаря (слово и его позиции)
public:
dict_el():Word(""){}; //Конструсторы
dict_el(string wd):Word(wd){};
~dict_el(){}; //Деструктор
void add_pos(const int i){ //Добавить позицию
this->pos.push_back(i);
};
bool operator==(const string& str){
/* сравнение со строкой для алгоритма find */
return (this->Word == str)? true:false;
}
friend ostream& operator<<(ostream& cout, dict_el& rhs);
/*Вывод слова и его позиций */
private:
string Word; //Хранимое слово
vector<int> pos; //Позиции для хранимого слова
};
ostream& operator<<(ostream& cout, dict_el& rhs){
/*Вывод слова и его позиций*/
cout << rhs.Word << ": ";
vector<int>::iterator i;
for (i = rhs.pos.begin(); i != rhs.pos.end(); ++i)
cout << *i << " "; //Выводит слово : и его позиции
return cout;
}
int get_word(string& str,string& res){ //получить следующее слово
static int current=0; //текущая позиция
int i;
while(isspace(str[current]) ) {
++current; //пропустить все знаки пробел,
} //переход строки и т.д.
if (str[current] == '\0') return EOS; //достигнут конец строки
i = current; //начало нового слова
res="";
while(!isspace(str[current]) && str[current] != '\0'){//считывать слово до конца
res+=tolower(str[current++]); //и записывать его в res
}
return i; //вернуть позицию слова
}
void parse_str(string& str, vector<dict_el>& dict){
/* Разбор строки и формирование словаря */
string temp; //следующее слово
int position; // и его позиция
vector<dict_el>::iterator i;
while((position=get_word(str,temp)) != EOS){ /*Пока не дошли до конца строки получить следующее слово */
i=find(dict.begin(),dict.end(),temp); //искать это слово в словаре
if (i == dict.end()){ //если такого слова нет
dict_el A(temp); //создать его
A.add_pos(position); //ввести первую позицию
dict.push_back(A); //и добать в словарь
}
else{ //если слово уже есть
(*i).add_pos(position); //добавть к нему новую позицию
}
}
}
//Начало программы int main(){ string str="Testing my Testing my program\0"; //Строка для разбора
vector<dict_el> dict; //Словарь
parse_str(str,dict); //Создать словарь
vector<dict_el>::iterator i;
for(i = dict.begin(); i != dict.end(); ++i){ //Вывести словарь
cout << *i << endl;
}
return 0;
}