Автор: Толик и Никита
Головной раздел: Меню
Чтобы обратиться не к компоненту класса, а сразу к указателю на него используются операторы ".*" и "->*". Перед использованием этих операторов сами указатели надо ещё настроить.
Шаг 1: Объявить указатель на поле: [тип] [класс]::*[имя_указателя]
Шаг 2: Настроить его на какое-то поле (сказать ему, на кого он показывает): [имя_указателя] = &[класс]::[поле]
Шаг 3: Использовать [объект класса].*[имя_указателя]
Шаг 3(другой): Тоже использовать [указатель на объект класса]->*[имя_указателя (на поле)]
Обратите внимание, что на шагах 1-2 используется имя всего класса, а на 3-3(др.) используется имя одного конкретного объекта или указателя на него
Пример:
class point{
public:
int x,y;
};
int main(){
int point::*p = &point::x; //Александр Юрьевич объединил шаг 1 и 2. Ну, бог ему судья
point p1; //Просто создаём объект
p1.*p = 5; //Уже третий шаг? Быстро же Вы, Александр Юрьевич
p = &point::y; //Снова второй? А вы шалун)))) По теме: здесь меняем указатель на другое поле
p1.*p = 10; //И снова третий. В этот раз изменения коснутся поля y.
}
Шаг 1: Объявить указатель на метод: [тип_возвр] ([класс]::*[имя_указателя])([параметры_метода])
Шаг 2: Настроить его на какое-то поле (сказать ему, на кого он показывает): [имя_указателя] = &[класс]::[метод]
Шаг 3: Использовать ([объект класса].*[имя_указателя])()
//другой шаг 3 додумайте сами
Обратите внимание2, по сравнению с предыдущим случаем, на первом и третьем шаге появляются скобки и при функции, и на всей конструкции.
Пример:
class point{
public:
int x,y;
int getX(){ return x;}
int getY(){ return y;}
};
int main(){
int (point::*pF)() //Шаг 1
pF = &point::getX(); //Шаг 2
point p1; //Просто создаём объект
cout << (p1.*pF)(); //Шаг 3
pF = &point::getY(); //Шаг 2 (меняем метод)
cout << (p1.*pF)(); //Шаг 3 (сработает для другого метода)
}
"Другом" класса называется функция или другой класс, НЕ ЯВЛЯЮЩИЕСЯ его методами(полями), но имеющие доступ к его приватным полям. Описать друга в классе легко - напишите его заголовок в классе с модификатором friend (в начале). Модификаторы доступа на друзей не влияют.
0) Не являются методами, и к классу имеют доступ, если мы
а) Его передали в аргументы (если не по ссылке/указателю, то поменять ничего не может :) )
б) Создали в самой функкции
1) В силу этого не имеют this
2) Могут быть методами других классов
3) Могут дружить с несколькими разными классами
0) Все методы друга могут иметь доступ к полям исходного
1) Метод - это функция, поэтому
#include "О друзьях-функциях"
Пример:
class A{
int a;
int b;
friend int get_a(A); //Говорят, по умолчанию для кого-то там private, но на друзей эти фокусы не работают
friend class B; //Ставь класс, если тоже не понимаешь, почему Никита до сих пор этим занимается
//friend idi::poesh(A); //Дружественная функция, которая метод poesh(A) класса idi. Закомментил - лень писать
};
class B{...}; //Про класс ничего крутого не придумал, но у меня есть отмаза: Быков тоже.
int get_a(A p){ //Посмотри в скобку для аргументов. Если туда не передать ничего, то зачем вообще эта дружба?
return p.a; //ДА, БЛ*ТЬ, Я СДЕЛАЛ ДРУГОМ ГЕТТЕР. И ЧТО ТЫ МНЕ СДЕЛАЕШЬ?
}
int main(){
A ga;
cout << get_a(ga);
}
Шаблон класса - синтаксическая конструкция, позволяющая на этапе компиляции генерировать класс по указанным аргументам шаблона. Пример:
template <class T, size_t S> // S можно передать только обычным числом, никаких переменных!
class SimpleArray // Шаблонный класс. Аргументы шаблона: тип, количество
{
T array[S];
public:
... // что-нибудь с ним можно поделать
};
Вопрос 33. Дополнительные операции преобразования типов: const_cast, dynamic_cast, static_cast, reinterpret_cast.
const_cast - снимает константность
const char *str = "hello";
char *str1 = const_cast<char*>(str);
dynamic_cast - преобразовывает типы в рантайме (полезно для преобразования указателей/ссылок базовых классов к производным).
Ошибкит: При преобразовании указателя базового к производному - nullptr
, ссылка - std::bad_cast
class Base
{
public:
virtual ~Base() = default;
};
class Derived: public Base {};
int main()
{
Base *ptr;
// ... что-то кладем в ptr
auto derived = dynamic_cast<Derived *>(ptr);
}
static_cast - преобразование типов, проверяемое на этапе компиляции
double b = static_cast<double>(777);
reinterpret_cast - самое небезопасное преобразование. Берет участок памяти и бахает под другой тип. Ничего не проверяет
auto waitWhat = *reinterpret_cast<void**>(777);
Вопрос 34. Понятие о динамической идентификации типов в Си++. Операция typeid. Основные функции класса typeinfo. Примеры
Динамическая идентификация типов позволяет получить информацию о типе в процессе работы программы.
typeid - идентификатор типа
typeinfo - позволяет получить объект типа std::type_info
, который содержит хэш типа, название типа
В обе функции передается любой объект
AbstractClass *ptr;
std::cout << typeid(*ptr).name() << std::endl;