Рассмотрим абстрактный класс ImageSource, представляющий данные изображения в формате RGB. Возможна различная реализация с разными глубинами цвета. Одна из реализаций могла выбрать пиксельное представление, подобное
struct Pixel{
uint8_t red;
uint8_t green;
uint8_t blue;
};
или другой
struct Pixel{
uint8_t red : 2;
uint8_t green : 2;
uint8_t blue : 2;
uint8_t : 2;
};
Я хотел бы создать ImageSource таким образом, чтобы я мог получить структуру, представляющую данные пикселя из определения класса, как в этом примере:
void debugPixel(ImageSource &source){
//ImageSource is abstract, each implementation may use a different pixel structure
uint8_t *data = source->getBuffer();
for(uint16_t i = 0; i < source->getWidth() * source->getHeight() * sizeof(source::Pixel); i += sizeof(source::Pixel)){
source::Pixel *pixel = data[i];
std::cout << "red: " << pixel->red << ", green: " << pixel->green << ", blue: " << pixel->blue;
}
}
ImageSource можно определить следующим образом:
class ImageSource{
public:
virtual uint8_t* getBuffer() = 0;
virtual uint16_t getHeight() const = 0;
virtual uint16_t getWidth() const = 0;
};
Есть ли способ получить тип (структура пикселя) из класса, если у меня есть только его экземпляр (я не знаю, какой тип ImageSource на самом деле)?
В приведенном выше примере вы хотите напечатать данные определенным образом, исходя из типа. Я уверен, что у вас будут другие методы.
Переместите Pixel в класс (вы также можете оставить его как структуру, очень близкую к классу в C++) и реализовать оператор вывода для каждого типа пиксельных объектов. Внесите в зависимости от того, какие другие методы вам нужны для типа Pixel внутри пикселя.
Затем вы позволяете языку определять тип и правильный метод для вас.
Вы можете использовать специализированные шаблоны.
В качестве примера (т.е. Вам нужно будет создать конкретный пример для каждого типа пикселов - здесь я обобщен с помощью bool
и int
):
template <typename T>
struct Print
{
static void print (const T v, FILE *op=(stdout))
{ return; }
};
template <>
struct Print<bool>
{
static void print (const bool v, FILE *op=(stdout))
{ fprintf (op, "%u", v); return; }
};
template <>
struct Print<int>
{
static void datafile (const int v, FILE *op=(stdout))
{ fprintf (op, "%d", v); return; }
};
Который вы бы использовали следующим образом:
#include <typeinfo>
void printPixel(Pixel *pixel)
{
Print<typeid(pixel->red)>::print(pixel->red);
return;
}
ImageSource
так как она предоставит детали реализации классов, реализующих базовый класс. Вы действительно хотите это сделать? Конечно, вы можете получить тип с помощьюenum
или другой техники, но вы этого хотите?