(23.04.2022)
Это не функция! это пример как создать что-либо!
допустим есть a.h файл в котором мы реализуем функцию, и ещё b.h, b.cpp и main.cpp. Допустим мы подклюаем a.h в b.h и main.cpp, при линковке возникает ошибка
В C++ в структурах можно реализовывать функции (методы)
struct My
{
int x;
} a, b, c
int myabs (My a) // копирует всю структуру
{
return abs(a.x);
}
int myabs (My *a) // норм
{
return abs(a->x);
}
int myabs (const My &a) // лучший вариант, но не бесплатный, тк лишнее обращение в память (про ссылку)
{
return abs(a.x);
}
struct My
{
int x;
int myabs()
{
return abs(x); // this->x (тоже самое)
// this - это указатель на того, кто вызвал метод
}
} a, b, c;
a.myabs();
b.myabs();
this передается как неявный аргумент метода, но в структуре не храниться!
методы создаеются с помощью name mangling, и они не принадлежат классу/структуре, мы лишь обьявляем, что они относятся к ним
struct My
{
int x;
int myabs()
{
return abs(x); // this->x (тоже самое)
// this - это указатель на того, кто вызвал метод
}
}
const My z = {2};
z.myabs() //не скомпилируется
struct My
{
int x;
int myabs() const // обьявляет что this - указатель на константные данные
{
return abs(x); // this->x (тоже самое)
// this - это указатель на того, кто вызвал метод
}
}
const My z = {2};
z.myabs() //скомпилируется
struct My
{
int x;
int myabs(int x) {return this->x + x;}
int myabs() const // обьявляет что this - указатель на константные данные
{
return abs(x); // this->x (тоже самое)
// this - это указатель на того, кто вызвал метод
}
}
struct My
{
int x; // рекумедуется называть как m_ (m_x), (как глобальные переменные называть начиная с g_)
static int y; // одна на все структуры такого типа переменная, но видно внутри структуры
// не создает y, надо в одном .cpp в глобальной области сказать
// int My::y;
static int f() {return 2;} // не получает this, но принадлежит только к структуре
int myabs() const
{
return abs(x);
}
}
My::y = 3; // к статическим полям можно оращаться без имени обьескта, а по имени типа
My::f(); // тоже можно
Matrix a, b;
float c;
a.add(b); // а хотелось бы a + b
a.add(c);
My operator+(const My &a, const My &b) //обычная функция (внешняя форма)
// & тк мы не хотим создавать копию
// const чтобы складывалить и константные структуры a + My{5}, например
{
My res;
res.x = a.x + b.x;
res.y = a.y + b.y;
return res;
}
c = a + b; //c = operator+(a, b);
struct My
{
int x;
int y;
My operator+(const My &b) const //метод класса (внутренняя форма)
//const после обьявления чтобы не менять текущий класс
// & тк мы не хотим создавать копию
// const в аргументах чтобы складывалить и константные структуры a + My{5}, например
{
My res;
res.x = x + b.x; // (this.x + b.x)
res.y = y + b.y; // (this.y + b.y)
return res;
}
}
c = a + b; //c = operator+(a, b);
оператор стандартный тип + структура возможно только во внешней форме
оператор = только во внутренней форме
operator(); //можно перегрузить оператор () и []
operator[];
My a;
a();
a[];
Про операторы - &&
и ||
вычисляется сокращенно, но их тоже можно перегрузить и не будет сокращенного вычисления, тк это уже функции, а не операторы
сокращенное вычисление - если мы знаем про тип выражения без второго аргумента, то он не будет вычислен напрмер,
if(p != NULL && p->x)
My operator++(My &x) //++a
{
}
My operator++ (My &x, int) //a++
//можем не указывать имя второму аргументу
//можем указать любой тип в качестве второго аргумента
{
}
My a, b, c;
(a+=b) += c; //хотитим поддерживать
struct My
{
My &operator+=(const My &b)
{
//...
return *this; // & съест * и разъименования на самом деле не произойдет
}
}
В
cout
просто переопределили оператор<<
методы можно разделить на
.h
и.cpp
my.h
struct My
{
int x;
int y;
int myabs(); //обьявления
}
my.cpp
int My::myabs() //реализация
{
}
методы реализованные в структуре рекомендуются компилятору как встраивымые (
inline
)
struct My
{
int x;
int y;
My (int a, int b = 0) {x = a; y = b}; // присвоение полям x, y
//My (const My &a) //есть по умолчанию
}
My c(2); //c.x=2, c.y = 0
//My z; //не скомпилируется
struct My
{
int x;
int y;
My () : x(0), y(0); //инициализация полей x, y
}
//My c(2); //не скомпилируется
My z; //c.x = 0, c.y = 0
struct My
{
int x;
int y;
My (int a=1, int b = 0) : x(a), y(b); //инициализация полей x, y
}
My c(2); //c.x = 2, c.y = 0
My z; //c.x = 0, c.y = 0
My z(); //ЭТО ПРОТОТИП ФУНКЦИИ
My z{}; //17 стандарт тоже самое My z;
My z = (); //ЭТО КОНСТРУКТОР
int x(2); //можно теперь писать, вызов конструктора int
~My() {} //деструктор, вызывается при уничтожениее обьекта, не принимает значений, нельзя перегрузить
int *p = new int(2); //скалярный оператор
int *arr = new int[10]; //веторный оператор
//...
delete p;
delete[] arr;
new
иdelete
вызывают конструкторы и деструкторы
Нет операций изменения размера (
realloc
)
Выделение памяти через malloc с конструкторами и деструкторами
My *p = (My *) malloc(sizeof(My));
//p->My(); //не скомпилируется
new(p) My(2, 3); //placement new
//просто вызывает конструктор
p->~My(); //деструктор вызывать можно руками
free(p);
Проверка на невыделение
int *p = new int(); //не вернет NULL, бросит эксепшн
#include <new>
unsing namespace std;
int *p = new(nothrow) int; //вернет NULL
в var arg можно передать только double (float неявно приводиться к double)
За жизнь Rust - язык без стандарта, свой компилятор языка без стандарта создать невозможно, тк то, как работает компилятор разработчика языка и является фактически стандартом. Переменные и Операторы int a, b = 5; // переменная a не инициализируется Инициализуется только переменные те у которых стоит = Локальные переменные без инициализации содержат мусор (рандомное значение), тк под локальные переменные место на стеке выделяется, но ничем не заполняется, может случиться 0, может не 0, из разных запусков - может случиться разное, из разных компиляций (release/debug) может случиться разное. Вообще, ошибки обращения к неиницилизированным переменным - это очень частые ошибки.
Jul 20, 2023За жизнь Сначала будет много про Си, тк Си++ - исходно расширение языка си: изначально он был как предпроцессор, который превращал его в си код, который потом компилировался - это был не отдельный язык, а надстройка над си. Потом C++ разошелся с си, некоторые вещи работают по-другому. Но в общем С++ можно считать надмножеством языка си, многое, что работает в си, работает и в ++. Идея - языка C/C++. Почему важно? - сильно влияет на проиходящие, стиль и т.д. Си относиться к одним из самых старых яп которые живы: старше си только фортран. Фортран создавался как язык для научных вычеслений, напрмер в нём легко работать с матрицами и т.д. А на си удобнее работать с системными функциями. Фортран часто используется в вычеслительных серверах. На нём написано много ПО, по этому яп до сих пор жив. Отметим, что ЯП бывают разные, так, например, Паскаль и вовсе создавался для обучения. -Для чего создавался си? -Системными программистами для себя.
Jul 20, 2023(19.03.2022) Про размеры Тип для размера массивов или чего либо другого - size_t - модификатор %z (%zu - стандарт C99) ptrdiff_t - для разницы двух указателей (size_t со значком) - модификатор %t (%ti или %td стандарт C99) (Данный тип описан в заголовочном файле stddef.h для языка C и в файле cstddef для языка C++) Обратный цикл для size_t: for(size_t x=N; x--; )
Sep 18, 2022(30.04.2022) Методы Методы - функции класса или структуры struct A { int x; int f() {return x;} };
Sep 9, 2022or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up