Site Tools


c

cppexample
вопросы на собеседование
Действия над char
Работа с файловой системой
dll (динамические) библиотеки
Время
связанные списки
инкапсуляция
интерфейс
абстрактный класс
композиция
делегирование
агрегация
осведомленность
функтор
аргументы функции\метода
*cast
приведение типов
битовое поле
исключения
указатель на функцию
конструктор копирования
специальные член-функции - конструктор копирования, преобразования, оператор присвоения, move(с++11), деструктор
примеры распарсивания объявлений
список инициализации

ключевые слова
Библиотеки
Направления
Hello World
#include <iostream>
using namespace std;

int main()
{
    cout << "Hello world!";
    return 0;
}
// Простейший класс
#include <iostream>

using namespace std;

class smallobj{
private:            // private - защищенные, недоступные из внешних функций, данные. Методы класса имеют доступ к другим приват-данным своего класса. (Один объект обращается к приват-данным другого объекта того же класса (Класс, можно передать в аргументе))
	int somedata; // Иногда называют "Поле класса"
public:
	void setdata(int a){ // метод класса
		somedata = a;
	}
	void showdata(){ // метод класса
		cout << "SomeData = " << somedata << endl; 
	}
};  

int Temp;
void main(){
	smallobj s1;
	cout << "Enter number" << endl;
	cin >> Temp;
	s1.setdata(Temp);
	s1.showdata();
}

структура

Инициализация → условие → тело → модификация

  • for(int i = 0; i > 15; ++i){some; some;}
  • for(int = 0; i > 15; ++i) some;
  • for(; i > 15;) some;
  • for(;;) some;

Условие → тело

  • while(){some; some;}
  • while(BoolVar){some; some;}
  • while(BoolVar) some;
  • if(BoolVar){some; some;}
  • if(BoolVar) some;
  • if(BoolVar){some; some;} else {some; some;}
  • if(BoolVar) some; else some;
  • if(BoolVar){some; some;} else if(BoolVar){some; some;} else if(BoolVar){some; some;} else {some; some}
  • if(BoolVar) some; else if(BoolVar) some; else if(BoolVar) some; else some ;
switch(Var)
{
  case "one":
    some;
    break;
  case "two";
    some;
    break
  case "three":
    some;
    break
  default:
    some;
}

Тело → условие

  • do{ some; some; }while(BoolVar);
  • do some; while(BoolVar);
  • result = (a < b) ? TrueSome : FalseSome ;
  • result = a < b ? TrueSome : FalseSome ;
  • SomeOperator (a < b ? TrueSome : FalseSome );
// Массив
* int VARNAME[99]; // Указатель размера массива, должен являться константой (определение его в момент запуска программы, возможно только с использованием ключевого слова new)
* int VARNAME[] = {5, 3, 6, 1}; VARNAME[1] == 3;
* int VARNAME[5] = {5, 3, 6, 1}; VARNAME[1] == 3; VARNAME[4] == 0;
* int VARNAME[3][3] = {{1, 2, 3},{4, 5, 6},{7, 8, 9}};// Массив может иметь сколько угодную многамерность.
* void FUNCNAME( int VARNAME[][3]); //При передачи массива в качестве аргумента, следует указывать его размер. Это указывается только при объевление функции.
При использование функции, передается только имя массива. Размер основного массива, является не обязательным, так как может быть вычислен компилятором.
Передача массива происходит по адресу, без копирования данных. (функция работает со значениями в оригинальном массиве)
* STRUCTNAME VARNAME[4]; VARNAME[1].POLLNAME = 'a'; определение массива структур и синтаксис доступа к полю структуры. Такойже синтаксис у массива объектов.
* У массива нет встроенной проверки границ. При работе с массивом с индексом за пределом его границ, ошибки выдано не будет, 
а программа будет продолжать работать с памятью котораю находится за пределами масива. Данный вид атаки, называется "Переполнение буфера"
/// Структура ///
struct NAME{
  int VARNAME;
  char VARNAME2;
  float VARNAME3;
}; // ; - обязательна

NAME VARNAME4;
VARNAME4.VARNAME = 1;
VARNAME4.VARNAME2 = 'a';
VARNAME4.VARNAME3 = 3.14;

/// инизиализация №2 ///
NAME VARNAME4 = {1  'a', 3.14};

/// вложенность ///
struct STNAME2{
  NAME NAMEPULL;
  NAME NAMEPULL2;
};
STNAME2.NAMEPULL.VARNAME = 1;
STNAME2.NAMEPULL.VARNAME = {{1, 'a', 3.14}, {2, 'b', 4.15}};

new MASSIVNAME[INTVAR + 10] // ключевое слово new - Возможность создания массива с "плавающим" размером массива. В ином случае, используется константа
///////////////////
  • enum ANIMAL{DOG, CAT, COW}; ANIMAL SOMEVAR; SOMEVAR = CAT; CAT == 1;
  • enum SOMENAME{NO, YES} /* NO = 0; YES = 1; */
// Функция с передачей аргумента по значению ( не изменяет исходную переменную )
void FUNCNAME(int VARNAME, char VARNAME2); // прототип
FUNCNAME(SOMEVAR, ANOTHERVAR);
void FUNCNAME(int VAR, char VAR2){ // объявление
    some;
    some;
}

// Функция с передачей аргумента №2 по ссылки ( изменяет исходную переменную )
void FUNCNAME(int VARNAME, char& VARNAME2);
FUNCNAME(SOMEVAR, ANOTHERVAR)
void FUNCNAME(int VAR, char& VAR2){
    some;
    some;
}
// Перегрузка функций.
void FUNCNAME(){some; some;}
void FUNCNAME(str){some; some;}
void FUNCNAME(int){some; some;}
void FUNCNAME(int, int){some; some;}
// Все используется в одно файле. При вызыве функции, выбирается подходящая функция по аргументам.
// Функция с аргументами по умолчанию
void FUNCNAME(char='a', int=45){some; some;}
void FUNCNAME(char CHARVAR='a', int INTVAR=45){some; some;}
  • inline void FUNCNAME(){some; some;} / / Встраиваемая функция (освобождаем процессор во вред RAM (на коротких функциях))
  • …{static int VARNAME; some;} / / Статическая переменная сохраняющая свое значение при заверешние блока.
// Возвращение аргумента по ссылки
  int x;
int& FUNCNAME();
FUNCNAME() = 92; // функция возвращает ссылку на переменную и пример равнозначен x = 92;
int& FUNCNAME(){
return x
}
// Константа в ссылочном аргументе или Запрет на изменение аргумента в виде ссылки.
int FUNCNAME(const int& a){ some; some; } // "а" передается в качестве ссылки, но попытка ее изменения вызывает ошибку.
int METODNAME(const int& a){ some; some; } // Доступно в методах класса.

const CLASSNAME OBJECTNAME(300, 'a'); // Объевляется констанктный объект класса. Возможно вызвать только константыне функции. Изменение данных внутри объекта недоступустимы.

* mutable - ключевое слово, которое позволяет изменять определенный антрибут, даже константным объектам. Ставится перед именем поля данных класса.
Классы
  • Структуры (struct) и классы (class) являются идентичными, но в классах по умолчанию используеются private а в структурах, по умолчанию используется public:. Но использование структур в виде классов не желательно.
// Класс, по умолчанию использует private
class CLASSNAME{
    int data;
public:
    void func();}

//идентично
class CLASSNAME{
private:
    int data;
public:
    void func();}
 
// Конструктор класса.
class CLASSNAME{
private:
    int VARNAME;
    char VARNAME2;
public:
    CLASSNAME(): // 1) Метод идентичен названию класса. 2) не имеет возвращаемый тип 
    VARNAME(3),       // Список инициализации. В С++ следует давать значение переменным между вызовом конструктора и его тела.
    VARNAME2('a')    // 1) Значение инициализированной переменной задается в скобочках 2) инициализации разделены запятыми, кроме последнего.
    {some; some;} // Тело конструктора. (может быть пустым)
};

...
// Пример задания антрибутов конструктора.
    CLASSNAME(char SOME):  // Конструктор с антрибутами
    VARNAME(3), VARNAME(SOME) {}

CLASSNAME OBJNAME('a');  // Создание объекта с заданием антрибутов.
...
...
// Пример перегрузки конструктора
    CLASSNAME(): VARNAME(3), VARNAME('a'){}
    CLASSNAME(char SOME): VARNAME(3), VARNAME(SOME){}
// Конструктор копирования по умолчанию
class CLASSNAME{
private:
    int VARNAME;
    char VARNAME2;
public:
    CLASSNAME(int A, char B): VARNAME(A), VARNAME2(B) // Конструктор объявлен для 2 аргументов. Конструктор с одиним аргументом типа класса не перегружен
}

CLASSNAME OBJNAME(4, 'a');
CLASSNAME OBJNAME2(OBJNAME);
CLASSNAME OBJNAME3 = OBJNAME; // Все 3 объекта инициализированны с параметрами (4, 'a'). Инициализация 2-ого и 3-го объекта, различны по синтаксису но идентичны по смыслу.
// Деструктор
class CLASSNAME{
private:
    int VARNAME;
    char VARNAME2;
public:
    ~CLASSNAME(){some; some;} // Деструктор идентичен конструктору, но содержит "~" вначале названия метода. Вызывается при уничтожение объекта. 
//Прототим метода и определение метода за классом.
class CLASSNAME{
...  
void METODNAME(int VAR, char VAR);
}; // конец класса
void CLASSNAME::METODNAME(int A, char B){ some; some; }
// static - внутри класса, делает общую переменную для всех объектов класса.
Изменение переменной в одной объекте, изменяет переменную во всех объектах.
int foo::count = 0 // определение (выделение памяти и указать значение "0") (может)происходит за пределами класса. 

// static метод. Использование метода, без класса.
CLASSNAME{
  static METODNAME(){some; some;}
}
CLASSNAME::METODNAME(); // использование мотода без объектов класса.
// const-антные функции
Сообщает, что внутри функции не будут действия по изменению переменных данного объекта, но позволяет изменять
созданные внутри метода переменные и (любые другие) внешние переменные.
CLASSNAME{
    void FUNCNAME()const{
        some; some;
    }
    void FUNCNAME2()const;
}
void CLASSNAME::FUNCNAME2()const{some;some;}
  • Класс можно возвращать из функции через return, с условием, что принимающий тогоже класса. (стр. 237)
// Узнать имя класса:
cout << typeid(*LINKTOCLASS).name() << endl;

// Проверить совпадение 2-ух классов:
FIRSTCLASS* LINK1; SECONDCLASS* LINK2 = new SECONDCLASS();
if( LINK1 = dynamic_cast<LINK1>(LINK2)){ some; some; }

// Изменить тип класса:
LINK1 = dynamic_cast<LINK1>(LINK2) // Изменение, возможно внутри иерархии наследования классов.
Ключевое слово this
  1. указывает на адрес своего объекта.
  2. нельзя использовать в статических методах класса. (уних нет объекта)

Строки

Строка как массив Char
// Предотвращение переполнения при вводе
cin >> setw(20) >> STRVAR; // Все более 19 символов, будет проигнорированно.
// Получение строки с символами пробела
cin.get(STRVAR, 20); // (Массив, Макс.колличество_символов)
// C символом переноса строки
cin.get(STRVAR, 20, '$') // 3 аргумент указывает символ, после которого функция будет завершена. По умолчанию '\n'  
Строка как класс string
#include <string>
// инициализация
string OBJ1("Hello");
string OBJ2 = "Hello";
string OBJ3;
// Доступные действия
* OBJ3 = OBJ1; Копирование
* OBJ1 + OBJ2; Конкатенация
* ОBJ1 == OBJ2; Проверка на идентичность
* OBJ1 < OBJ2; Проверяется первая буква строки. True, если первая буква OBJ1 идет раньше по алфавиту чем 1-ая буква OBJ2
* OBJ1[10]; Возвращает символ в 10 позиции. Аналог OBJ1.at(), но в отличии от него, не имеет проверки выхода за границу массива.
// Методы
* OBJ1.swap(OBJ2); Замена друг на друга.
* OBJ1.find("Some"); Возвращает int позиции в строке где встречается "Some".
* OBJ1.find_first_of("abs"); Возвращает int позиции в строке, где впервые встречается один из символов 'a', 'b', 's'
* OBJ1.find_first_not_of("abs "); Возвращает int позиции в строке, где впервые отсутствует один из символов 'a', 'b', 's', ' '
* OBJ1.erase(0, 10) - Удаление фрагмента. (Позиция, размер_удаления)
* OBJ1.replace(0, 10, "Some") - Заменяет первые 10 символов на "Some" 
* OBJ1.insert(0, "Some") - Вставляет "Some" в нулевую позицию
* OBJ1.append(3, '!') - Добавляет "!!!" в конец строки. 
* OBJ1.compare(0, 2, "SOME", 0, 2); Проверяе совпадение символов в определенных позициях строки.
* OBJ1.lenght() - возвращает int размер строки
* OBJ1.at(10) - возвращает символ в 10 позиции строки
* OBJ1.copy(MASSIVVAR, VARLEN, 0) - Копирование строки
* OBJ1.capacity() - возвращает текущий объем занятой памяти на данную строку.
* OBJ1.max_size() - Возвращает значение максимаольно возможного объема на строку.

Перегрузка операций

//Операция и их методы в классе.
///Унарные
operator++(){some;}  - Префиксная ++VAR
operator++(int){some;} - Постфиксная VAR++ // Тип int является лишь сигналом для компилятора и не используется.
operator--(){some;}
operator--(int){some;}
///Бинарные
Вызывается слева стоящим операндом, а правый операнд от операции передается в качестуе аргумента.
TYPE operator+( TYPE VAR ){some;} - оператор сложения. В поле TYPE можно использовать тип данных, классы и т.д.
TYPE operator<( TYPE VAR ){some;} - оператор сравнения < 
TYPE operator>( TYPE VAR ){some;} - оператор сравнения >
TYPE operator==( TYPE VAR ){some;} - оператор сравнения ==
TYPE operator[]( TYPE VAR ){some;} - доступ по индексу. Пример: int& operator[](int n){return VAR[n];}

TYPE operator = (TYPE VAR){some;} - _Не наследуется!_. Оператор присвоения по умолчанию. Используется в виде OBJ1 = OBJ2. 
//Избегаем ситуации OBJ1 = OBJ1:
if(this == $ARGVAR){return *this} // Если адресс объекта переданного по аргументу(левый операнд от "=") такой же как правый операнд(присвоение самого к сибе), то просто возвращаем ссылку на себя.
//Перегрузка копирования по умолчанию
CLASSNAME OBJ1(OBJ2); CLASSNAME OBJ1=OBJ2; //Пример использования "копирования по умолчанию"

CLASSNAME{
  CLASSNAME(CLASSNAME& LOCALVAR){some; some;} // операция "копирования по умолчанию" перезагружена.
}
Аргумент в "копирование по умолчанию" должен передаваться по ссылки (CLASSNAME&) иначе операция поподет в цикл и вызовет переполнение памяти.
// Равенство
/// Пользовательский тип = Стандартный тип
Достаточно перегрузить конструктор с одним аргументом. Пример:
class CLASSNAME{
public:
    CLASSNAME(int){some;}
}
CLASSNAME = 9;

/// Стандартный тип = Пользовательский тип
class CLASSNAME{
public:
    operator float (){some;}
}

float FVAR;
FVAR = CLASSNAME; // неявное преобразование
FVAR = static_cast<float>(CLASSNAME); //явное преобразование

Пример для строки:
operator char*(){some;}
static_cast<char*>CHARVAR;

// Пользовательский тип CLASSNAME1 = Пользовательский тип CLASSNAME2
Приоритет у CLASSNAME1
/// Преобразование со стороны CLASSNAME1:
CLASSNAME1(CLASSNAME2 VAR){some; some}
/// Преобразование со стороны CLASSNAME2:
operator CLASSNAME1 (){some; return CLASSNAME1(SOMEVAR)}
// Неперегружаемые операции:
.   ::  ?:  ->
новые операции не могут быть созданы.
// Пример подстановки типа при компиляции.
OBJ3 = OBJ2 + 10;
Если в используемом этими объектами классами, перезагружена операция "+" с операндом этого же класса, но не перезагружена с int типом операнда, то компилятор подставит заместо 10, CLASSNAME(10). Тоесть OBJ3 = OBJ2 + CLASSNAME(10) 
// Перегрузка самого оператора (не в рамках какого-то класса.)
OBJ3 = 10 + OBJ2; // Оператор "+" обрабатывается левым операндом (int) в котором не предусмотрено действие с нашим классом.
Для этого, мы можем перегрузить оператор "+" следующим образом:
CLASSNAME operator + (CLASSNAME, CLASSNAME){
  some; some;
} 
Если в процессе использование оператора +, необходим доступ к приватным полям класса, то следует использовать дружественные функции. (стр. 491)
// Перегрузка << и >>
friend ifstream& operator >> (istream& s, MyClass& d){cin >> d.some;} // Пример >>
friend ofstream& operator << (ostream& s, MyClass& d){cout << d.show();} // Пример <<
  • explicit - ключевое слово предотвращающее не явное преобразование типов. Может использоваться перед именем конструктора класса.

Наследование класса

class SECONDCLASS: public FIRSTCLASS{
some; some;
}
По умолчанию, используется ключевое слово private перед именем наследуемого класса, а не public. При private, в объекте производного класса мы не иммем доступа к публичным данным наследуемого класса.

//Множественное наследование 
class SECONDCLASS: public FIRSTCLASS, public ANOTHERCLASS{
some; some;
}
//Наследование конструктора
SECONDCLASS(int i, char c): FIRSTCLASS(i, c){
some; some;
}
//Модификация(дополнение) базовой функции
METOD(int i){
some; some;           //Добавляем функционал
FIRSTMETOD::METOD(i)     // Выполняем функцию из базового метода
}
  • protected - ключевое слово. Аналог private но позволяет иметь доступ из производных классов.
// Неоднозначность при множественном наследование:
Если наследуется более одного класса в которых присутствует функция с одинаковым именем
и производный класс попытается вызвать данную функцию, то компилятором будет выдана ошибка.
При неоднозначности наследования, объект должен указывать класс для которого он хочет вызвать метод:
OBJ1.CLASSNAME1::METODNAME();

Ссылка и Указатель

Ссылка

<TYPE> &<NAME> = INTVAR; // Создается ссылка на INTVAR. Обладает темиже свойствами, что и сама переменная INTVAR
&<NAME>; // Получение адреса переменной.
  1. Ссылка не может указывать на NULL и должна инициализироватся каким либо значением.
  2. Ссылка не может быть переопределена к другим переменным.

Указатель

<TYPE> *<NAME> = &INTVAR; // Создает указатель на переменную INTVAR
*<NAME>; // Разыменование указателя (обращение к значению по адресу указателя)

Примеры

Передача в качестве аргумента
void func(int &var){ var = 2;} // Значение передается по ссылки, и изменение переменной в функции отражаются на значение самой переменной.
void func(int *var){ *var = 2;} // Значение передается по указателю. В функции можно изменить саму переменную, обращаясь к ней с использованием разыменования.
Возвращение из функции
int &func(int var){ ++var; return var;} // Возвращаемое ссылку.
int *func(int var){ ++var; return &var;} // Возвращает указатель (адрес переменной).

В данном случае, пример не корректен, так как var существует пока выполняется функция.

Остальное
// Переменная-указатель (Переменная содержащаяя в себе данные о адресе и размере другой переменной)
int* PTRVAR; PTRVAR = &INTVAR;
int *PTRVAR; int * PTRVAR; int* PTRVAR; - объявления идентичны. Можно использовать любой из приведенных синтаксисов.
int *PTRVAR1, *PTRVAR2, *PTRVAR3; - множественное объявление.
*PTRVAR1 = 10; - операция "разыменования" или "непрямого доступа". Доступ к переменной по ее адресу.
CLASSNAME* PTRVAR; PTRVAR = &METODNAME;
// Массив и указатель
int MASSIV[3] = {1, 2, 3};
MASSIV[2] == 3;
*(MASSIV + 2) == 3;  // Выражение идентично верхнему. MASSIV + 2 означает адресс массива в памяти + 2 раза по int(4 байта). Выражение указывает на 3ий элемент массива.
Массив - (хранит в себе адрес)указатель на первый элемент его типа.

Массива (переменная), является константной переменной-указатель. Чтобы интеррировать адрес, следует передать его неконстантной переменной.
MASSIV++ // Нельзя
int* PTRVAR; PTRVAR = MASSIV; *(PTRVAR++) // Возможно  
//указатель как аргумент функции
class CLASSNAME(int* VAR1){
*VAR1 += 10;
}

int INTVAR = 3;
CLASSNAME(&INTVAR);
//Указатель на массив как аргумент функции
class CLASSNAME(int* VAR1){ // Передача адреса из INTMASS в VAR1 происходит по значению(копирование). В итоге, мы можем изменять _адрес_ VAR1 без последствий для INTMASS.
*VAR1 += 10; *(++VAR1) +=10;
}

int INTMASS[3] = {1, 2, 3};
CLASSNAME(INTMASS); // Операция взятия адреса (&) не используется, так как имя массива уже возвращает адресс.
  • int *PTRINT; PTRINT = reinterpret_cast<int*>(&FLOATVAR); - преобразование типа указателя.
//указатель на строковый массив
char* STR1 = "Some"
char[] STR2 = "Some" // Стандартный способ
// const и указатель
const int* MASSIV; Указатель на константу
int* const MASSIV; Константный указатель (как имя массива)
// Указатель на объект класса
CLASSNAME* PTRCLASS;
PTRCLASS = new CLASSNAME;
CLASSNAME->METHODNAME();
(*CLASSNAME).METHODNAME(); // Операция идентична предыдущей. Разыменовывает указатель на объект и использует "." для доступа к методу.
// Указатели на указатели (Стр.449)
LINKTOLINKVAR**;
//
CLASSNAME* OBJMASSIV[100] // Массив указателей на объекты класса CLASSNAME // Тип->УказательНаОбъектКласса* НазваниеМассива[РазмерМассива]
OBJMASSIV[10] = new CLASSNAME; // Создание объекта класса. // УказательНаОбъектКласса->АдресВПамяти = new CLASSNAME
OBJMASSIV[10]->METHODNAME(); // Использование метода объекта, находящегося в массиве объектов // УказательНаОбъектКласса->Метод 
// Использование в качестве аргументов
FUNCNAME(CLASSNAME** LOCALVAR){
LOCALVAR[10]->METHODNAME()
*(LOCALVAR+10)->METHODNAME()
}
FUNCNAME(OBJMASSIV)
//Простой пример связанного списка (Связанные списки) Стр.445
struct STRUCTNAME{
  int SOMEINTDATA;  // Структура, содержит данные и ссылку на другую структуру. 
  STRUCTNAME* NEXT;
}

class CLASSNAME{ // Класс предоставляет организацию по работе со связанными структрурами.
private:
  STRUCTNAME* FIRST;  // Ссылка на первую структуру (последняя введенная структура, является первой (LIFO))
  
  CLASSNAME(){
    FIRST = NULL;}  // Назначем нулевые данные на последнюю ссылку, чтобы иметь сигнал о конце списка.
  
  void ADDITEM(int LOCALVAR){
    STRUCTNAME* NEWLINK = new STRUCTNAME;  // В новом, свободном, не зарегистрированном участке памяти, создаем новую структуру. 
    NEWLINK->SOMEINTDATA = 1;
    NEWLINK->NEXT = FIRST;  // Если это первая структура, то она указывает на 0. Если последующая структура, то указывает на свою предшественницу.
    FIRST = NEWLINK;  // Следующая структа, будет указывать на ЭТУ структуру.
  }
  
  void SHOWLIST(){
    STRUCTNAME* CURRENT = FIRST; //Начинаем с последнего введенного элемената
    while(CURRENT){
      cout << CURRENT->SOMEINTDATA <<endl;
      CURRENT = CURRENT->NEXT;  // Переходим к следующему списку. И так, до NULL
    }
  }
}

Виртуальные функции

//
class BASECLASS{
  public:
    void SHOW(){
      cout << "Base" << endl;
    }
}
class CLASS1 : public BASECLASS{
  public:
    void SHOW(){
      cout << "Class1" << endl;
    }
}

CLASS1 OBJ1;
BASECLASS* PTRCLASS;
PTRCLASS = &OBJ1;
OBJ1.SHOW();     // Выводит Class1.
PTRCLASS->SHOW(); // При обращение по указателю, выводит "Base" (метод базового класса, а не наследуемого)
// Если в базомо классе, установить ключевое слово virtual, перед методом, то будет обращение к методу наследуемого класса, а не базового.
class BASECLASS{
  virtual void SHOW(){some;some;}}

// Абстрактный класс и нулевая виртуальная функция
// Если в классе создать виртуальную функцию, то создание объектов этого класса, будет недоступно. При попытки создать объект этого класса, будет возвращена ошибка. Применяется в базовых классах, которые созданы только для наследования.
class BASECLASS{
  virtual void show() = 0;   // "= 0" означает не присвоение, а назначает виртуальную функцию. 
}
  virtual void some() =0  // Виртуальная функция, может содержать тело функции, для прямого ее вызова, через ::
  {some:some}
виртуальных функций в классе, может быть сколько угодно. Ими обозначаются функции, которые должны быть переопределены в наследуемых классах.
Если в наследуемом классе не будет переобпредлена виртуальная функция базового класса, то при создание объекта наследуемого класса, так же будет возвращена ошибка о абстрактности класса.
Деструктор, так же следует делать виртуальным при необходимости.

// виртуальный класс (стр.488)
class CLASSNAME : virtual public BASECLASS{ // В наследуемом классе, указывается виртуальность базового класса
  some; some;
}
Виртуальный класс используется для устранния неоднозначности, в случае неоднозначности для наследования.
Дружественные функции (стр.489)
Объявление дружественной функции(метода), позволяет обратиться к приватным данным другого, дружественного класса.
friend int METODNAME(FRENDCLASSNAME);
Ключевое слово friend используется только при объявление функции\метода.
Объявляется в каждом дружественном классе. Если функция должна иметь доступ к классу, то:
friend TYPE FUNCTIONNAME(THISCLASSNAME); // внутри класса
TYPE FUNCTIONNAME(THISCLASSNAME){some; some} // Сама функция.
Дружественным может быть весь класс. К примеру:
FIRSTCLASS{
  private:
    int DATA 1;
    friend class SECONDCLASS;
}
В этом случае, SECONDCLSS2 будет иметь доступ к приватным данным FIRSTCLASS.
В SECONDCLASS указывается ключевое слово friend, только если FIRSTCLASS должен иметь доступ к данным SECONDCLASS.

Упралвение памятью

new - ключевое слово, позволяющая выделить необходимый объем памяти. Возвращает адрес на начало выделенной памяти.
char* ptr; ptr = new char MASSIV[INTVAR + 100];
delete - ключевое слово, освобождающее память для дальнейшего использования. При освобождение, значение в памяти или сама переменная не удаляются, а помечаются как доступные для записи.
delete ptr;
delete [] ptr; // Квадратные скобки необходимы если удаляется массив.

I\O

Список флагов и функций ios для форматирования текста, доступен на странице http://developers.sun.com/sunstudio/documentation/ss12u1/mr/man/man3cc4/ios.3.html

  • cin.good() - возвращает bool, если ввод без ошибок
  • cin.ignore(streamsize n = 1, int delim = EOF) - игнорируем символы в потоке, до n символов или пока не встретится делимитр.
  • cin.clear(iostate state = goodbit) - устанавливает бит ошибки. Без аргументов, устанавливает бит “ошибки отсутствуют”
Флаги
	 skipws	   = 0x0001,	 - игнорирование пробела и новой строки. Пример:cin.unsetf(ios::skipws) - не игнорировать пробелы и символы новой строки.// skip whitespace on input
	 left	   = 0x0002,	 // left-adjust	output
	 right	   = 0x0004,	 // right-adjust output
	 internal  = 0x0008,	 // padding after sign or base indicator
	 dec	   = 0x0010,	 // decimal conversion
	 oct	   = 0x0020,	 // octal conversion
	 hex	   = 0x0040,	 // hexidecimal	conversion
	 showbase  = 0x0080,	 // use	base indicator on output
	 showpoint = 0x0100,	 // force decimal point	(floating output)
	 uppercase = 0x0200,	 // upper-case hex output
	 showpos   = 0x0400,	 // add	'+' to positive	integers
	 scientific= 0x0800,	 // use	1.2345E2 floating notation
	 fixed	   = 0x1000,	 // use	123.45 floating	notation
	 unitbuf   = 0x2000,	 // flush all streams after insertion
	 stdio	   = 0x4000	 // flush stdout, stderr after insertion

Файлы

  • #include <fstream> - содержит ввод\вывод для файлов
  • OBJfstream(“Filename”, bits) Где bits:
  • ios::in - вход в программу (чтение из файла)
  • ios::out - выход из программы (запись потока в файл)
  • ios::app - режим добавления при записи (коретка перемещается в конец)
  • ios::ate - Чтение начинать с конца файла.
  • ios::binary - в двоичном режиме (Рекомендуется при работе с не текстовыми данными)
  • ios::trunc - если файл существет, то очистить его.
  • ios::nocreate - Не создовать файл, если файл несуществует
  • ios::noreplace - Не производить перезапись имеющихся данных (Следует установить ios::ate или ios::app)
  • Пример: OBJfstream(“Filename”, ios::in | ios::out | ios::app| ios::binary);
Запись
  • ofstream CLASSNAME(“Filename”) - класс для вывода в файл. Пример вывода: Filename « “Some”; (Перезапись)
  • CLASSNAME.put('s') - посимвольный вывод
  • OBJofstream.write(reinterpret_cast<char*>(&SomeObj), sizeof(SomeObj)); Пример записи объекта.
  • OBJfstream.write1); Еще один пример записи объекта. (Множественная запись разных объектов, демонстрируется на стр.559)
Чтение
  • ifstream CLASSNAME(“Filename”) - класс для чтения из файла. Пример вывода: Filename » stringVAR
  • CLASSNAME.eof() - возвращает bool, true если в буфере находится EOF
  • CLASSNAME.get(char) - посимвольное чтение.
  • CLASSNAME.get(str) - построчное чтение.
  • fstreamOBJ.read( reinterpret_cast<char*>(&SomeObj), sizeof(SomeObj)); Пример чтения объекта из файла. (Запись приводилась выше)
  • getline()
  • putback() - вставляет последний символ обратно.
  • peek() - читаем один символ, оставляя его в потоке.
  • gcount() - возвращает число символов прочитанных только что в потоке
  • seekg() - Устанавливает положение корретки.
  • tellg() - Возвращает положение корретеки.

Память

  • #include <strstream> - позволяет работать с памятью как с дисковым накопителем. (стр. 583)
С чем работаем?
  • cin » - стандартный вход
  • cout « - cтандартнй выход
  • сerr « - cтандартный вывод ошибок
  • clog « - стандартный вывод лога.
  • ClassFile « » - вывод или ввод для объекта файла или другого потока.
  • ofstreamObj.open(“PRN”); ofstreamObj « “Some” « '\xOC'; - вывод на стандартный принтер (не проверено.)

Аргументы коммандной строки

main(int argc, char* argv[]){some; some;} // argc - колличество аргументов. argv[index] - строка аргумента. 
argv[0] - всегда путь до исполняемого файла.

Многофайловость

Библиотеки, как правило распространяются с заголовоными файлами ((интерфейс) исходный код) и библиотечный(.lib)\объектный(.obj) файл ((реализация) скомпилирован)
extern - объявляет переменную в файле. Дает доступ к глобальной переменной из другого файла. Не используется при инициализации (extern int Var = 1; плохо.)
static - Сужает область видимости глобальной переменной со всех файлов проекта, до файла в котором находится переменная.
Комилятор - компилирует исходные тексты.
Компановщик - Используется при компиляции. Добавляет откомпилированные(объектные) файлы к компиляции.
Компановка FileB.obj при компиляции FileA.cpp используется комманда cl /EHsc FileA.cpp FileB.obj
Получение объектного файла из исходного кода, происходит при его компиляции.
Область видимости

При использование разных файлов с исходным кодом и использованием #include для них, файл считается за один. Разными файлами считаются файлы(объектные) добавленные компановщиком при компиляции. _При компановке_:

//// переменная ////
По умолчанию:
Видима из разных файлов. Но при обращение, вызывается ошибка

Для многофайлового доступа:
Декларируем переменную c extern в каждом файле где используем ее:
//AFile
int SomeVar;  
//BFile
extern int SomeVar;
SomeVar = 4;

Для однофайлового ограничения:
Указываем слово static перед деклорацией переменной:
//AFile
static int Somevar;
//BFile
static int Somvevar; В каждом файле, своя переменная со своим значением.
//// Функция ////
По умолчанию:
Видима из разных файлов. Но при обращение, вызывается ошибка

Для многофайлового доступа:
Декларируем функцию в каждом файле где используем ее:
//Afile:
int Func(int a){some;}
//Bfile:
int Func(int); Func(4); // Используем функцию указанную в Afile

Для однофайлового ограничения:
//Afile:
static int Func(int a){some;}
//Bfile:
static int Func(int a){some;} // В каждом файле, своя функция
// Класс
По умолчанию:
Видима из разных файлов. Но при обращение, вызывается ошибка

Для многофайлового доступа:
Необходимо _определение_(не декларация) в каждом используемом файле.

Для однофайлового ограничения:  
Заголовочные файлы
Код в заголовончном файле, применяется к каждому исходному файлу. (Копируется в каждый исходный файл.)
//fileH.h
extern int gloVar;
int gloFunc(int);

//fileA.cpp
int gloVar;
int gloFunc(int n){some;some;}

//fileB.cpp
#include "fileH.h"
gloVar = 5;
gloFunc(gloVar);
// Использование блоков define для предотвращения множественного копирования.
#if !defined(SomeDirectiv) // (Раньше, использовать #ifndef ) Если SomeDirectiv не инициализироваллась:
#define SomeDirectiv      // Инициализируем SomeDirectiv и выполняем код до #endif
int SomeVar;
int func(int a, int b){some; some;}
#endif
Пространство имен
namespace SomeName{
  int SomeVar;
  int SomeFunc(){some;some;}
}
SomeName::SomeVar = 10;
SomeName::SomeFunc();
using namespace geo; // Действуют от объявления, до конца файла. Если в функции, то доконца функции.
SomeVar = 11
Тесты
      //FileB
#include <iostream>
using namespace std;
char fileb = 'b';
void showChar(){
	cout << fileb << endl ;
}
class TestClass{
	char ClassChar;
public:
	void SetChar(char Ch){
		ClassChar = Ch;
	}
	void ShowChar(){
		cout << ClassChar << endl;
	}
};
      //FileA
#include <iostream>
#include "FileB.cpp"
using namespace std;
char filea = 'a';
void main(){
	cout << "This is FileA.cpp" << endl;
	cout << fileb << endl;
	fileb = 'y';
	cout << fileb << endl;
	showChar();
	TestClass ClassFromB;
	ClassFromB.SetChar('c');
	ClassFromB.ShowChar();
}

Тестируется на VB2010:

  1. Видит переменную из FileB
  2. Имеет доступ на ее изменение
  3. Видит функцию showChar из FileB и корректно использует ее.
  4. Класс TestClass доступен из FileB и корректно использует ее.
Вопросы

Бесконечно большие числа

Пример реализации математики со скольки угодно большими числами, представлен на странице 613. (Название файла verylong.cpp verylong.h)

Шаблон

template <class T> 
T abs(T n){             // Значение T будет вычесленно при передачи аргумента и будет являтся корректным типом аргумента.
return (n<0) ? -n : n ;
}

template <class OneType, class TwoType> // Использование нескольких шаблонных типов
...
//Class
template <class OneType>
class MyClass{
  OneType Var;
  some; some;
}

MyClass<int> OBJCLASSINT; // Присоздание объекта, следует указывать тип для подставления в шаблоны.

template <class OneType>
MyClass<OneType>::METOD(){some; some;} // Использование шаблона, при опредеделие методов вне класса.

Обработка ошибок

class CLASSNAME{
  public:
    class ERRORNAME{};
    
    void FUNC(){
      some;
      if(SomeError){
        throw ERRORNAME();
      }
    }
};

try{
  CLASSNAME OBJNAME;
  OBJNAME.FUNC();
}
catch(CLASSNAME::ERRORNAME){
  cout << "Some Error" << endl;
}
Для передачи аргументов ошибки, используется конструктор класса ошибки и его выхов с использованием:
throw ERRORNAME("Some Error", 12);

catch(CLASSNAME::ERRORNAME OBJ){
  cout << "Error:" << OBJ.STRERROR << OBJ.ERRORCODE << endl;
}

STL

Контейнеры

Последовательные контейнеры


#include <vector>

Вектор - массив с автоматическим управлением памяти, который сам заботится о своем размере. FIFO. Вход\выход с одной стороны. Поддерживает произвольный доступ через индекс []
vector<TYPE> VAR - Создает вектор определенного типа, где в TYPE указывается тип.
Методы:
push_back("Some") - поместить в конец списка.
size() - текущее число объктов.
max_size() - максимально возможное колличество объектов для данного вектора.
back() - выводит значение последнего элемента
pop_back() - удаляет последний элемент
insert(VAR.begin()+5, "Some") - Вставить "Some" в 5 позицию вектора (Медленная операция)
erase(VAR.begin()+5) - Удалить 5 элекмент из вектора (Медленная операция)

#include <list>

Список - организован как "Связанный список". Похож на Вектор, но Вход\выход осуществляется с 2-ух сторон. Доступ через индекс [] отсутствует.
list<TYPE> VAR - Создание списка.
Методы:
push_back("Some") - Поместить в конец списка
push_front("Some") - Поместить в начало списка
size() - текущее число объктов.
front() - выводит значение элемента в начале
back() - выводит значение последнего элемента
pop_front() - удаляет первый элемент
pop_back() - удаляет последний элемент
reverse() - Перевернуть список
unique() - Удалить повторяющиеся элементы, оставив только уникальные значения в списке.
merge(MASSIVE) - объеденяет данный массив с массивом MASSIV

#include <deque>

Очередь с двустороннем доступом - похож на список, но имеет произвольный доступ по индексу []
deque<TYPE> VAR - Создание очереди с двусторонним доступом.
Поддерживается и LIFO и FIFO
Хорошо:
доступен доступ по индексу. VAR[3] = "Hello"
Плохо:
Методы:
push_back("Some") - Поместить в конец списка
push_front("Some") - Поместить в начало списка
size() - текущее число объктов.
Ассоциативные контейнеры

http://cs.smu.ca/~porter/csc/ref/stl/cont_set.html

Множества, мультимножества set<string, less<string> > nameSet(names, names+5); set<pair<key_class,value_class> >
У множества отсутствуют дупликаты. В остальном, контейнер похож на списки.

http://cs.smu.ca/~porter/csc/ref/stl/cont_map.html

Отображение, мультиотображение   map<key_class,value_class>
Отображение, всегда использует данные с доступом по ключу

Алгоритмы

#include <algorithm>

  • find(MASSIV, ENDMASSIV, VALUESEARCH) - возвращает адрес на искомое значение
  • search(MASSIV, ENDMASSIV, VALUESEARCH, ENDVALUESEARHC) - В отличии от find может искать последовательности значений.
  • sort(MASSIV, ENDMASSIV) - сортировка по значению
  • merge(MASSIV, ENDMASSIV, 2MASSIV, 2ENDMASSIV, NEWMASSIV) - объединяет 2 массива в 3-тий
  • find_if(MASSIV, ENDMASSIV, USERFUNC) - где USERFUNC функция определенная нами для поиска.
  • for_each(MASSIV, ENDMASSIV, USERFUNC) - выполнение пользовательской функции для каждого элемента в массиве
  • transform(MASSIV, ENDMASSIV, NEWMASSIV, USERFUNC) - тоже что и for_each но помещает результат в другой массив.

#include <functional> Функциональные объекты, могут быть использованы как флаги в функциях STL

sort(MASSIV, ENDMASSIV, greater<double>()) - с использование greater<TYPE>() происходит сортировка по убыванию

В качестве функциональных объектов, могут использоваться пользовательские функции. Это позволяет регулировать способ сортировки. Пример такого кода, представлен на стр.693

Not Sorted

объявление → определение

int SomeVar; //Объявление и определение
extern int SomeVar; // Объявление
  • static_cast<type>(Var) - изменение типа переменной, где type указание нового типа.
  • typedef int* ptrInt; ptrInt p1, p2; - typedef создает синонимы. typedef [ЧтоПодразумевается] [чтоМыБудемПисатьТеперь]

Библиотека

CrossPlatform

iomanip
setw(int) - Установка размера столбца. Пример cout << setw(10) << "Some" << setw(10) << "Some else"
setfill(char) - заполнить пробелы между столбцами данным символом. Пример Пример cout << setfill('.') << setw(10) << "Some" << setw(10) << "Some else"
setprecision(2) - определяет точность(колличество знаков) после запятой
// setiosflags() 

ios::left - выравнить стобец по левой границе. Пример cout << setiosflags(ios::left) << setw(10) << "Some" << setw(10) << "Some else"
ios::fixed - Печатает полное число предотвращая печать в стиле 3.45e3
ios::showpoint - Печатает всегда с точкой. Вместо числа 120 будет выведенно 120.00

Windows

process.h
* exit(int)
conio.h
getche() - Получаем символ. Пример ch = getche()
getch() - тоже что и getche() но без эхо на экран

Не тестил на Linux

// ctime
time(NULL); - возвращает системное время.
//cstdlib
srand(SOMEINT); - инициализирует генератор случайных чисел. Пример: srand(time(NULL));
rand(); - возвращает случайное число. Пример получения случайного значения из 50: rand() % 50;
// cstring
strlen(STRVAR); - возвращает int размер строки
strcpy( DESTINATIONSTRVAR, SOURCESTRVAR); - копирует строки из одной переменной в другую.
strncpy( DESTINATIONSTRVAR, SOURCESTRVAR, 20); - 3 аргумент указывает максимальное число символом при копирование.
// string
Сам класс string для взаимодействия со строками
getline(cin, STROBJ [, '$']); - Получаем строку со стандартного ввода. (Поток, объект_string [, символ_заверешения. По умолчанию '\n'])

Linux

Вопросы

  • обращение внутри класса без self. Что будет, когда глобальная переменная пересекается с внутре-классовой переменной?
  • int foo::count = 0; Назначает “0” экземпляру класса (не созданному объекту), да еще и приватному полю данных.
  • Чем отличается ссылка от указателя

Ссылка - разыменованный указатель. Указатель содержит адрес в памяти. Его разыменование значение, возвращает не адрес в памяти а само значение.

Глоссарий
  • :: - оператор разрешения, разрешения области видимости
  • Переменная в классе - Член класса, Поле класса, Поле данных класса.
  • private - Частное.
  • Наследование класса с указанием его private - Частным производного класса.
  • &VAR - операция получения адреса
  • подпрограмма - функция возвращающая void
  • Полиморфизм - Концепция при которой разные классы имеют общие методы. Подробнее, смотрите “Виртуальные функции”. К примеру, мы имеем картину пинающего мальчика. Объект который пинает мальчик рисуется классом который мы предоставим основному классу. Мы можем предоставить класс который рисует мячик ( boll→draw() ) или наковальню ( nakaval→draw() ). Дейсвия в этих классах, могут быть совершенно разные, но они могут быть использованы основным классом для рисования объекта (без информации о имени класса, так как оба класса содержат методы draw()).
  • Инкапсуляция -

глоссарий английских выражений

Sites

TMP

1) char*)(SomeObj), sizeof(SomeObj
You could leave a comment if you were logged in.
c.txt · Last modified: 2013/04/20 19:02 by konovalov

Page Tools