Всем привет! Решил на выходных продолжить писать свой домашний проект и наступила пора реализовать платформозависимый код. Самым простым вариантом было бы описать классы в *.h файле, а в зависимости от платформы, закрытые поля засунуть под #define. При этом, саму реализацию по конкретным платформам разнести по *.cpp файлам и включать их в компиляцию в зависимости от текущей платформы. Но... мне не нравится как выглядит описание класса с #define, поэтому я решил убрать препроцессор и оставить в описании класса только интерфейс. И да, я не пользовался абстрактными классами и pimpl, всё еще хуже :-) Основной язык автора С. Данный материал не несет в себе цель оскорбить или еще как-то нанести вред приверженцам чистого кода. Также автор не претендует на новизну, поскольку идея, по сути, тривиальна. Информация предоставлена исключительно потому как автор посчитал ее забавной. Продолжим. Какие варианты здесь приходят сразу на ум. У меня два: Использовать абстрактный класс с виртуальными методами, затем наследовать его и реализовать эти методы. Добавить статичный метод для создания конкретного экземпляра. Воспользоваться техникой pimpl (Pointer to Implementation), когда в исходном классе только указатель на другой класс/структуру, который(ая) реализует требуемый функционал или содержит поля с данными. Первый вариант мне не нравится поскольку на ровном месте создается ненужная дополнительная нагрузка (тот самый overhead) в виде таблицы виртуальный методов. По сути это указатели на функции. Возможно при некой оптимизации какой-нибудь компилятор додумается оптимизировать вызовы, возможно. Второй вариант тоже не нравится, ибо для доступа к полям скрытого класса нужно каждый раз считать еще одно смещение. К тому же здесь есть дополнительная нагрузка в виде вызова new/malloc для скрытого класса/структуры. Но ясен пень так нельзя И тут я подумал, а можно ли реализовать класс, который будет без этих дополнительных нагрузок и при этом не надо будет в описании класса декларировать закрытые поля. Тут я задумался как бы я сделал это на чистом С и у меня возникла идея. Экстремально простая. Естественно, не без минусов, но об этом позже. Необходимо при вызове new для класса выделять память для другого (скрытого) класса, ну или структуры. К примеру имеется у нас описание класса со следующими методами (файл Render.h): У каждой платформы своя реализация и свои закрытые поля у этого класса, но объявлять мы их здесь не будем. Лучше объявим их в новой структуре в исходном файле, к примеру LinuxRender.cpp: Теперь переопределим для класса Render операторы new и delete. Теперь у нас при создании экземпляра объекта выделяется память для скрытой структуры. И мы можем использовать данные этой структуры в методах класса Render. К примеру добавим метод initialize. Вот собственно и вся идея. Но, воскликнет читатель, что будет если класс Render будет создан не через new, а, к примеру, в стеке или глобально. И тут начинаются минусы. Тут я скажу что всё сломается) Ибо sizeof(Render) будет 1, поскольку полей класс Render не имеет. Лепим костыли. Поэтому надо запретить создавать класс не через new. Для этого делаем конструкторы закрытыми. А также создадим статичный метод create для создания экземпляров класса. Здесь можно добавить ещё один костыль в виде статичного метода sizeOf, ибо sizeof не будет выдавать правильное значение. Я, конечно, получил что хотел. Но здесь есть минусы: Автоматически вычисленные фишки компилятора, такие как sizeof или еще какие-либо операции над типом работать не будут. И тут надо четко понимать что вы делаете, ибо можно выстрелить себе во все места на ровном месте. Необходимость переопределять для каждого класса оператор new Нельзя выделять память под экземпляр объекта без new (по умолчанию, стек, глобальная память работать не будут) Необходимость создания метода для каждого подобного класса, который будет создавать экземпляр этого класса Еще не очень удобно в каждом методе класса приводить тип к скрытому классу/структуре (LinuxRenderData *pdata = (LinuxRenderData *)this) Поэтому не рекомендую пользоваться никому. Рассматривайте статью как запоздалый пятничный юмор :-)