Skip to content

Instantly share code, notes, and snippets.

@NickTikhomirov
Last active June 19, 2019 18:05
Show Gist options
  • Save NickTikhomirov/65c9d3ed32a879b70ea29fc5b5ed9ea0 to your computer and use it in GitHub Desktop.
Save NickTikhomirov/65c9d3ed32a879b70ea29fc5b5ed9ea0 to your computer and use it in GitHub Desktop.
Разное (указатели, динамические типы, друзья, шаблоны)

Вопросы 6-8,33,34, Остальное

Автор: Толик и Никита

Головной раздел: Меню

Билет 6. Указатели на компоненты класса (на функции и поля класса), назначение, пример.

Чтобы обратиться не к компоненту класса, а сразу к указателю на него используются операторы ".*" и "->*". Перед использованием этих операторов сами указатели надо ещё настроить.

Указатель на поле.

Шаг 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 (сработает для другого метода)
  }

__________________________________________________________________

Билет 7. Дружественные функции и классы, назначение, пример

"Другом" класса называется функция или другой класс, НЕ ЯВЛЯЮЩИЕСЯ его методами(полями), но имеющие доступ к его приватным полям. Описать друга в классе легко - напишите его заголовок в классе с модификатором 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);
  }

__________________________________________________________________

Билет 8. Шаблоны классов. Примеры использования

Шаблон класса - синтаксическая конструкция, позволяющая на этапе компиляции генерировать класс по указанным аргументам шаблона. Пример:

template <class T, size_t S>  // S можно передать только обычным числом, никаких переменных!
class SimpleArray             // Шаблонный класс. Аргументы шаблона: тип, количество
{
    T array[S];
public:
    ...     // что-нибудь с ним можно поделать
};
Cпасибо за этот билет Толяну, мировой мужик!

__________________________________________________________________

Вопрос 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;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment