Форум программистов, компьютерный форум CyberForum.ru

указатели на элементы класса - C++

Восстановить пароль Регистрация
Другие темы раздела
C++ Все положительные элементы двумерного массива записать в один одномерный массив, а остальные в другой http://www.cyberforum.ru/cpp-beginners/thread650273.html
Дан двумерный массив размером n на n заполнены целыми числами. все его положительные элементы записать в один одномерный массив а остальные в другой
C++ склеить 2 wav файла /* Написать программу, формирующую из двух WAV файлов третий путем конкатенации файлов. */ #include <stdio.h> #include <conio.h> #include <stdlib.h> #include <Windows.h> typedef struct { http://www.cyberforum.ru/cpp-beginners/thread650271.html
опредилить общую стоимость C++
известны данные о мощности двигателей (в л.с.) и стоимость 30 легковых машин . определить общую стоимость автомобилей у которы больше 100 л.с
Как считывать данные из файла? C++
как считывать и записывать данные из файла по строкам в переменную?
C++ зачем ставить ";"(пустую инструкцию два раза) в цикле for http://www.cyberforum.ru/cpp-beginners/thread650256.html
for (i = 0; ; i++) Добавлено через 1 минуту одну убираешь прог не пашет. Пожалуйста подскажите
C++ прототип функции Использовать прототип функции То есть заголовок перед функцией main, а описание функции в теле функции main немогу с аргументами которые в скобках разобратся,куда что ставить чтобы работало(( #define MAX 1000 // Функция ввода строки с клавиатуры void getLine(char str, int m) { int c, i; подробнее

Показать сообщение отдельно
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
12.09.2012, 04:06     указатели на элементы класса
Если подумать, то для вызова невиртуального метода через указатель,
живой объект не очень то и нужен. Ведь не нужно шарится по таблице
виртуальных функция для поиска правильной функции. С указателем
на виртуальный метод совсем другое, потому что таблица виртуальных
функция находится по смещению относительно адреса объекта, для
которого этот метод зовется. Что стандарт говорит относительно
первого утверждения - хз, но студия и компилер из ссылки
делают вызов невиртуального метода имея нулевой указатель на
объект. То, что в методе this оказывается равным нулю - это
уже отдельная история. Если к полям класса не обращатся,
ничего не упадет.


http://liveworkspace.org/code/036ec3...7b4592b61a7bfd


Далее, вот например указатель на метод:
typedef void (Foo::*MethodPtr)();
Тут нигде не кодируется его виртуальность\невиртуальность.
Поэтому, можно прикинуть, что компиляторы реализуют
указатели на методы в виде какой-то структуры,
в которой есть флажок о виртуальности\невиртуальности метода
и другие поля, позволяющие сделать правильный вызов.
Для невиртуальных методов будет использоваться поле,
в которой указатель на метод похож на указатели на свободные
функции (с учетом того, что сигнатура несколько расширена
за счет неявной передачи this и может быть соглашения о
вызове другие). А вот в случае указателя на виртулальный
метод используются другие поля. Например просто индекс
функции в таблице виртуальных функций, ведь для вызова
виртуального метода через указатель нужен сам объект
для определения, где таблица функций и смещение на указатель
к нужному методу.

Ну примерно это можно было бы описать так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
typedef void (Foo::*MethodPtr)();
//примерно эквивалентно
struct MethodPtr
{
  bool isVirtual;
  void (*nonVirtPtr)(Foo*);
  int virtFunPtrOffset;
};
 
{
  MethodPtr nonVirtPtr = &Foo::NonVirtual;
  MethodPtr virtPtr = &Foo::Virtual;
 
  // после этого поля у ptr будут такими:
  //nonvirtPtr.isVirtual == false;
  //nonvirtPtr.NonVirtPtr == указатель на функцию
  //nonvirtPtr.virtFunPtrOffset == неопределено. пусть будет -1
 
  //virtPtr.isVirtual == true;
  //virtPtr.NonVirtPtr == не определено. пусть будет 0
  //virtPtr.virtFunPtrOffset == смещение в таблице. пусть будет 0 (т.е. первый метод в таблице)
 
   //далее код вызова превращается в следующее
 
   MethodPtr ptr = nonVirtPtr;
   //MethodPtr ptr = virtPtr;
 
   Foo* foo = 0;
   foo->*method)();
   if (ptr.isVirtual)
   {
      // Получение указателя на табличку. Может крашнутся,
      // а может и нет. Просто вернется указатель на хз что.
      // Ведь чтобы получить указатель на таблицу, компилятору
      // нужно знать лишь адрес объекта и сместится относительно
      // него на определенное известное во время компиляции значение.
      // нет особого смысла проверять корректность адреса объекта,
      // к нему достаточно прибавить нужное смещение. Если адрес
      // объекта будет кривой, то и адрес таблички тоже будет кривым
      // жопа случится при попытке вызвать что-то из этой таблицы.
      
      VTable vtbl = GetVTableOfObject(foo);
      // В этом месте у нас есть таблица и индекс функции в этой
      // таблице. Сигнатура метода тоже известна.
      (vtbl[ptr.virtFuncOffset])(foo);
 
      // в случае кривого указателя на таблицу вот это:
      // vtbl[ptr.virtFuncOffset] - тоже кривое.
 
   }
   else
   {
     // в этой ветке для вызова метода сам объект вроде как и не нужен.
     // метод вызовится ну а крашнется или нет уже зависит от кода 
     // самого метода. Главное что метод вызовится.
     (ptr.nonVirtPtr)(foo);
   }
}
 
Текущее время: 12:08. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru