Вопрос Inheritance

Начинающий
Статус
Оффлайн
Регистрация
30 Мар 2020
Сообщения
275
Реакции[?]
21
Поинты[?]
9K
Почему наследование может слегка наебнуть проект или челибо?


Сидел и делал ченжер,

есть у меня клаcc:

C++:
class CSharedObject;

class C_EconItem : public CSharedObject
{ 
public:

    virtual void* Destructor(bool bImmediately) = 0;
    virtual void* DllMain() = 0;
    virtual void* sub_181CDD630() = 0;
    virtual void* vcrt_uninitialize_critical_129() = 0;
    virtual void* sub_181CDD850() = 0;
    virtual void* sub_181CDD860() = 0;
    virtual void* Dump() = 0;
    virtual void* BAddToMessage() = 0; //; #STR: "CEconItem::BAddToMessage::std::string", "Steam"
    virtual void* BAddDestroyTomessaage() = 0;
    
     
    void* vmt1; // 0x0008
    uint64_t m_ItemID; //0x0010
    uint64_t unk; //0x0018
    uint32_t m_AccountID; //0x0020
    uint32_t m_numInventory; //0x0024
    uint32_t m_DefIndex; //0x0028
    uint8_t m_Flags; //0x002C
    uint8_t m_Level; //0x002D
    uint8_t m_Quality; //0x002E
    uint8_t m_Origin; //0x002F

    style_index_t m_unStyle;                // Style

    dirty_bits_t m_dirtyBits;    // dirty bits

     
    EquippedInstance_t m_EquipInstanceSingleton; 
    attribute_t m_CustomAttribSingleton;    

 
    CEconItemCustomData* m_pCustomData;

    void EnsureCustomDataExists();

    void Equip(equipped_class_t unClass, equipped_slot_t unSlot);

    void UnequipFromClass(equipped_class_t unClass);
}; // 0x50
Обычное наследование,беды здесь нету вродебы.

Но как только я добавляю шмотку в кэш:
C++:
auto Object = CreateSharedObjectEconItem();

                Object->m_ItemID = i + 100;
                Object->m_numInventory = i + 1;
                Object->m_DefIndex = itemdef->DefinitionIndex;
                /*Object->m_Flags = 1;
                Object->m_Level = 4;
                Object->m_Quality = 1;
                Object->m_Origin = 34;
                Object->m_unStyle = 0;*/
                Object->m_AccountID = g_InventoryManager->GetPlayerInventory()->soid.SteamID;
                g_DOTAGCClientSystem->SOCache->AddObject(Object); <-------------  здесь случится хуйня
Смотрел в реклассе и вмтшки Object-а выглядит вот так

CEconItem : GCSDK::CSharedObject : IEconItemInterface
CEconItem : GCSDK::CSharedObject : IEconItemInterface

А после добавления в кэш(после функи AddObject)

ВМТ какогото хера стает таким:

GCSDK::CSharedObject
IEconItemInterface

Но адреса на которые они указывают(вмтшки) вроде бы не меняются.

И шмотки нихера не добавляются в инвентарь.

Чтобы пофиксить данную и непонятную ошибку, потребовалось удалить наследование CEconItem::CSharedObject. И просто вручную кастовать при добавлении в кэш
C++:
g_DOTAGCClientSystem->SOCache->AddObject((CSharedObject*)Object);
В чём прикол с этим не пойму? Нельзя делать наследования на вальвоские классы?
 
feel irl
Участник
Статус
Оффлайн
Регистрация
21 Дек 2018
Сообщения
679
Реакции[?]
295
Поинты[?]
16K
Может какой-нибудь указатель на втейбл или что-нибудь такое сдвигает какие-нибудь важные данные?
 
Начинающий
Статус
Оффлайн
Регистрация
30 Мар 2020
Сообщения
275
Реакции[?]
21
Поинты[?]
9K
Максимально описал всё на фотодоказательстве

На момент написания поста я действительно заметил что там меняются вмтшки, беспонятия
(Нижняя фотография показывает код который вызывает ошибку тоесть в данном случае с наследованием,)





А здесь показываю что я сделал чтобы не произошло ошибки в связи с скрином 1


 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
673
Реакции[?]
313
Поинты[?]
45K
Максимально описал всё на фотодоказательстве

На момент написания поста я действительно заметил что там меняются вмтшки, беспонятия
(Нижняя фотография показывает код который вызывает ошибку тоесть в данном случае с наследованием,)





А здесь показываю что я сделал чтобы не произошло ошибки в связи с скрином 1


1) вмт меняются скорее всего потому что объект деструктируется
2) когда ты(в сценарии с наследованием) пишешь AddObject(Object) у тебя происходит автоматический статик_каст из C_EconItem* в CSharedObject*
3) когда ты(в сценарии без наследования) пишешь AddObject((CSharedObject*)Object) это с-стайл каст, а с-стайл каст автоматически выбирает статик каст/реинтерпрет каст/конст каст по возможности. тут возможности статик каста нет(нет наследования) поэтому выбирается реинтерпрет, а реинтерпрет тупой и он ничего не делает с указателем в техническом плане
4) все виртуальные классы всегда с втейблов начинаются
т.е. ВИРТУАЛЬНЫЙ C_EconItem НЕ НАЧИНАЕТСЯ с НЕВИРТУАЛЬНОГО CSharedObject. он начинается с ВТЕЙБЛЫ, потом идёт порция CSharedObject, потом идёт уже остальная порция C_EconItem.
поэтому когда ты делаешь статик кастом CSharedObject* это значит ты скипаешь первую втейблу, т.е. прибавляешь 8 байт к указателю, и получаешь указатель на порцию CSharedObject(потом этот кривой указатель передаешь в функцию которая ахуевает естественно от такого)
когда ты реинтерпрет кастуешь(в сценарии без наследования), там ничего не прибавляется ибо реинтерпрет каст ничего не делает в техническом плане
5) не юзай с-стайл касты пока не научишься понимать какой каст что делает, юзай конкретно статик касты где надо и реинтерпрет касты где надо.
6) просто сделай CSharedObject виртуальным и хуйней не занимайся. если делаешь наследование - делай его правильно(т.е. как у габена, раз ты его наследование повторяешь). C_EconItem не сам себе виртуальную таблицу выростил, он ее частично унаследовал от CSharedObject. у тебя же CSharedObject не имеет виртуальной таблицы(хотя у габена имеет)
7) сравни статик каст и реинтерпрет каст что выводят
C++:
#include <iostream>

class base
{
    int y{333};
    //virtual void w() {}
};
class derived : public base
{
    virtual void x() {}
    int z{ 444 };
};
int main()
{
    derived x{};
    std::cout << &x << std::endl;
    std::cout << reinterpret_cast<base*>(&x) << std::endl;
    std::cout << static_cast<base*>(&x) << std::endl;
}
 
feel irl
Участник
Статус
Оффлайн
Регистрация
21 Дек 2018
Сообщения
679
Реакции[?]
295
Поинты[?]
16K
то с-стайл каст, а с-стайл каст автоматически выбирает статик каст/реинтерпрет каст/конст каст по возможности.
А си-стайл каст разве не может вести себя динамик каст? Или может казаться видимость его использования, но в самом деле это будет статик\реинтерпрет каст?
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
673
Реакции[?]
313
Поинты[?]
45K
А си-стайл каст разве не может вести себя динамик каст? Или может казаться видимость его использования, но в самом деле это будет статик\реинтерпрет каст?
1684687662979.png
динамик каст
1) на рантайме происходит(по вмтхам там всякую хуйню чекает)
2) может вернуть нуллптр если провалился, поэтому его результат надо чекать
с-стайл каст это просто автокаст этакий который бегает по всем возможным компайл-тайм кастам и выбирает подходящий
 
Сверху Снизу