с++: указать для класса интерфейс с методами так, чтобы не менять размера объекта класса

подскажите, можно ли реализовать следующую идею:

есть интерфейс

class IBase {
public:
    virtual operator CData() const = 0;
}

есть соответствующий класс

class CChild : public IBase {
public:
    operator CData() const;

public:
    int m_data;
}

изначально (когда не было базового класса) через CChild считывались данные из файла (записанные в бинарном виде, т.е. блоками по sizeof(CChild))

но затем, когда был введен базовый класс это стало невозможным, поскольку virtual увеличивает размер объекта на размер указателя (8байт для 64битной сборки)

такой вопрос - как обойти данную проблему

понятно, что можно

  1. отказаться от наследования, но очень было хотелось показать, что у CChild обязательно должен быть метод operator CData() const; (ну отчасти из-за эстетических соображений, отчасти из-за того, что таких классов CChildX несколько и у каждого своя начинка, свои размеры, но у всех есть один и тот же обязательный метод)

  2. не делать наследование от абстрактного класса (чтобы не было virtual методов), но тогда возникают проблемы с универсализацией использования :(

Подскажите как обычно выходят из данной проблемы?


Ответы (3 шт):

Автор решения: HolyBlackCat

Наследование убрать, а наличие (и правильность сигнатуры) метода проверять концептом, или, до C++20, SFINAE.

→ Ссылка
Автор решения: AlexGlebe
class CData{
};

class IBase {
public:
    virtual operator CData() const = 0;
};

class CChild {
public:
    operator CData() const;
public:
    int m_data;
};

class VCChild1 : public IBase , public CChild {
public:
    virtual operator CData() const {return CChild::operator CData();}
};

// или так

class VCChild2 : public IBase {
public :
  CChild c ;
  virtual operator CData() const {return CData(c);}
};

В файл записывать статический элемент объекта static_cast<CChild&> или CChild c ;. А экземпляр с виртуальными функциями из класса VCChild будет работать.

→ Ссылка
Автор решения: αλεχολυτ

Из данной проблемы выходят сериализацией. Не нужно опираться на бинарное представление экземпляра класса в памяти для его хранения на диске. Даже в случае Plain Old Data (без виртуальности, наследования и разных модификаторов доступа) могут играть роль выравнивания, да и просто размеры конкретных полей данных (sizeof(int) может разниться от системы к системе). Поэтому, чтобы сохранять и в последствии загружать (заполнять) объекты надо использовать сериализацию. В текущем виде вопрос выглядит как ошибка молотка.

→ Ссылка