Если классы с виртуальными функциями реализованы с vtables, как класс без виртуальных функций реализован?

Простым способом форматирования объектов вашего домена в JSON является использование сериализатора Маршала . Затем передайте данные в json_encode и отправьте правильный заголовок Content-Type для ваших нужд. Если вы используете фреймворк вроде Symfony, вам не нужно заботиться о настройке заголовков вручную. Там вы можете использовать JsonResponse .

Например, правильный Content-Type для работы с Javascript будет application/javascript.

Или, если вам нужно поддержка некоторых довольно старых браузеров самым безопасным будет text/javascript.

Для всех других целей, таких как мобильное приложение, используйте application/json как Content-Type.

Вот небольшой пример :

 $user->getUsername(),
        'email'    => $user->getEmail(),
        'birthday' => $user->getBirthday()->format('Y-m-d'),
        'followers => count($user->getFollowers()),
    ];
}, $userCollection);

header('Content-Type: application/json');
echo json_encode($data);

6
задан Brian R. Bondy 19 September 2008 в 12:11
поделиться

9 ответов

Не виртуальные функции членства являются действительно просто синтаксическим сахаром, поскольку они почти похожи на обычную функцию, но с проверкой доступа и неявным параметром объекта.

struct A 
{
  void foo ();
  void bar () const;
};

в основном то же как:

struct A 
{
};

void foo (A * this);
void bar (A const * this);

vtable необходимо так, чтобы мы вызвали правильную функцию для нашего экземпляра конкретного объекта. Например, если мы имеем:

struct A 
{
  virtual void foo ();
};

Реализация 'нечто' могла бы приблизиться к чему-то как:

void foo (A * this) {
  void (*realFoo)(A *) = lookupVtable (this->vtable, "foo");
  (realFoo)(this);   // Make the call to the most derived version of 'foo'
}
12
ответ дан 8 December 2019 в 02:47
поделиться

Виртуальные методы требуются, когда Вы хотите использовать полиморфизм. virtual модификатор помещает метод в VMT для позднего связывания, и затем во времени выполнения решен, какой метод, из которого выполняется класс.

Если метод не является виртуальным - он решен во время компиляции, от которого экземпляр класса будет он выполняться.

Указатели функции используются главным образом для обратных вызовов.

3
ответ дан 8 December 2019 в 02:47
поделиться

Я думаю, что фраза "классы с виртуальными функциями реализована с vtables", вводит в заблуждение Вас.

Фраза заставляет его казаться, что классы с виртуальными функциями реализованы "способом", и классы без виртуальных функций реализованы "способом B".

В действительности, классы с виртуальными функциями, в дополнение к тому, чтобы быть реализованным, поскольку классы, у них также есть vtable. Другой способ видеть его состоит в том, что "'vtables' реализуют часть 'виртуальной функции' класса".

Больше деталей, на как они оба работа:

Все классы (с виртуальными или невиртуальными методами) являются структурами. Единственная разница между структурой и классом в C++ - то, что по умолчанию участники являются общедоступными в структурах и частными в классах. Из-за этого я использую термин класс здесь для обращения и к структурам и к классам. Помните, они - почти синонимы!

Элементы данных

Классы (как структуры), просто блоки непрерывной памяти, где каждый участник хранится в последовательности. Обратите внимание, что несколько раз будут разрывы между участниками для ЦП архитектурные причины, таким образом, блок сможет быть больше, чем сумма его частей.

Методы

Методы или "функции членства" являются иллюзией. В действительности нет такой вещи как "функция членства". Функция является всегда просто последовательностью команд машинного кода, сохраненных где-нибудь в памяти. Для звонка процессор переходит к той позиции памяти и начинает выполняться. Вы могли сказать, что все методы и функции 'глобальны', и любой признак обратного является удобной иллюзией, осуществленной компилятором.

Очевидно, метод действует как он, принадлежит конкретному объекту, так ясно там больше продолжается. Для связи конкретного вызова метода (функция) к конкретному объекту каждый членский метод имеет скрытый аргумент, который является указателем на рассматриваемый объект. Участник скрыт в этом, Вы не добавляете, что это к Вашему C++ кодирует себя, но нет ничего волшебного об этом - это очень реально. Когда Вы говорите это:

void CMyThingy::DoSomething(int arg);
{
    // do something
}

Компилятор действительно делает это:

void CMyThingy_DoSomething(CMyThingy* this, int arg)
{
    /do something
}

Наконец, когда Вы пишете это:

myObj.doSomething(aValue);

в компиляторе говорится:

CMyThingy_DoSomething(&myObj, aValue);

Никакая потребность в указателях функции где угодно! Компилятор уже знает, какой метод Вы называете так, он называет его непосредственно.

Статические методы еще более просты. У них нет этого указателя, таким образом, они реализованы точно, как Вы пишете им.

Это! Остальное - просто удобный синтаксис sugaring: компилятор знает, которые классифицируют метод, принадлежит, таким образом, он удостоверяется, что не позволяет Вам вызвать функцию, не указывая который. Это также использует то знание для, переводит myItem кому: this->myItem когда это однозначно, чтобы сделать так.

(да, правильно: членский доступ в методе всегда делается косвенно через указатель, даже если Вы не видите один),

(Редактирование: Удаленное последнее предложение и отправленный отдельно, таким образом, это может быть подвергнуто критике отдельно),

15
ответ дан 8 December 2019 в 02:47
поделиться

Если класс с виртуальной функцией реализован с vtable, то класс без виртуальной функции реализован без vtable.

vtable содержит указатели функции, должен был отправить вызов соответствующему методу. Если метод не является виртуальным, вызов переходит к известному типу класса, и никакая косвенность не необходима.

1
ответ дан 8 December 2019 в 02:47
поделиться

Для невиртуального метода компилятор может генерировать нормальный вызов функции (например, ЗВОНИТЕ в конкретный адрес с этим указателем переданный в качестве параметра), или даже встройте его. Для виртуальной функции компилятор обычно не знает во время компиляции, в котором адресе вызвать код, поэтому он генерирует код, который ищет адрес в vtable во времени выполнения и затем вызывает метод. Правда, даже для виртуальных функций компилятор может иногда правильно разрешать правильный код во время компиляции (например, методы на локальных переменных, вызванных без указателя/ссылки).

1
ответ дан 8 December 2019 в 02:47
поделиться

(Я вытянул этот раздел из своего исходного ответа так, чтобы он мог быть подвергнут критике отдельно. Это намного более кратко и на грани Вашего вопроса, так способом это - намного лучший ответ),

Нет, нет никаких указателей функции; вместо этого, компилятор поворачивает вывернутую наизнанку проблему.

Компилятор вызывает глобальную функцию с указателем на объект вместо того, чтобы звонить, некоторые указали на функцию в объекте

Почему? Поскольку это обычно намного более эффективно тот путь. Непрямые вызовы являются дорогими инструкциями.

1
ответ дан 8 December 2019 в 02:47
поделиться

Ответвления сгенерированы непосредственно к скомпилированному коду для методов; точно так же, как, если у Вас есть функции, которые не находятся в классе вообще, ответвления сгенерированы прямо им.

0
ответ дан 8 December 2019 в 02:47
поделиться

Нет никакой потребности в указателях функции как он изменение наклона во время времени выполнения.

0
ответ дан 8 December 2019 в 02:47
поделиться

Компилятор/компоновщик связывается непосредственно, какие методы будут вызваны. Никакая потребность в vtable косвенности. BTW, что это имеет отношение "к стеку по сравнению с "кучей""?

0
ответ дан 8 December 2019 в 02:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: