о размере WinRt Демо-объект - PullRequest
0 голосов
/ 01 декабря 2019

Мне любопытен размер очень простого демо-объекта, поэтому я пишу следующий код

</p>

#include <windows.h>
#include "winrt/base.h"
#include <iostream>
#pragma comment(lib, "windowsapp")
/*
cl /nologo /await /std:c++latest /wd4002 /EHsc base_so.cpp
*/
using namespace std;
using namespace winrt;
using namespace winrt::impl;

struct IDemo;

template <typename D>
struct consume_IDemo
{
  void hello();
};

template <> struct consume<IDemo> { template <typename D> using type = consume_IDemo<D>; };

template <typename D> void consume_IDemo<D>::hello()
{
  WINRT_SHIM(D)->hello();
}

struct WINRT_EBO __declspec(uuid("3A44B7CC-9CB6-4512-8CAD-6400E662D865")) 
IDemo : Windows::Foundation::IInspectable, consume_t<IDemo>
{  
  IDemo(std::nullptr_t = nullptr) noexcept {};
};

template <> struct abi<IDemo>
{
  struct type : IInspectable
  {
    virtual HRESULT hello() = 0;
  };  
};

template <typename D>
struct produce<D,IDemo> : produce_base<D,IDemo>
{
  HRESULT hello() override
  {
    shim().hello();
    return S_OK;
  }
};

struct Demo : implements<Demo,IDemo>
{ 
  Demo()
  {
    cout << "sizeof Demo 0x" << hex << sizeof(*this) << dec << endl;
    cout << "sizeof m_references 0x" << hex << sizeof(std::atomic<std::conditional_t<1, uintptr_t, uint32_t>>) << dec << endl;
    cout << "is_composing " << is_composing << endl;
    cout << "outer " << outer() << endl;    
  }

  HRESULT hello()
  {
    cout << __FUNCTION__ << endl;
    return S_OK;
  }
};

int main()
{
  Demo d;
}

и выводим

size of Demo0x18
sizeof__references 0x8
is_composing 0
external 0000000000000000

Я думаю, что размер Demo должен быть 0x10 (64 машины): sizeof (m_references) + sizeof (производить), так что же это за дополнительные 8 байтов? большое спасибо!

1 Ответ

0 голосов
/ 01 декабря 2019

Это либо padding, либо v-таблицы. Может быть, оба ...

Компилятор может вставить указатель v-таблицы для каждого базового класса, в котором объявлен хотя бы один виртуальный метод. (Кроме того, когда вы выполняете C-cast, static_cast или dynamic_cast из конкретного класса в не первый базовый класс, компилятор изменит значение указателя на значение базового класса или его v-таблицы. )

Давайте разберемся с этим.

Demo наследуется от implements<Demo,IDemo>

implements определяется следующим образом:

struct implements : impl::producers<D, I...>, impl::base_implements<D, I...>::type
{

Сейчасмы попадаем в шум WinRT. Но это, кажется, предполагает множественное наследование. Но проще разобраться с этим, отладчик .... Вот так. Первый vtable для IUnknown. Другое относится к IInspectable.

Так что это имеет смысл. Каждая v-таблица является 8-байтовым указателем. И m_references также 8 байтов. 8+8+8 = 24 = 0x18

enter image description here

...