У меня есть (частично реализованная) иерархия классов, где
template<typename T> {
class data {
data ( string s ) {}; // loads from file
...
}
class image: public data <T> {
image ( string s ) {}; // loads from file
...
}
class jpgimage : public image<T> {
jpgimage ( string s ) {}; // loads from file
...
}
// other image types
}
Теперь в остальной части моего кода я хотел бы иметь возможность абстрагироваться от того, что-то изображение jpeg или даже изображение, поэтому я хотел бы работать с data
. Но в то же время я хотел бы передать команды, специфичные для jpeg-изображений, для этих функций.
Поэтому, если я вызываю data<int> img("lena.jpg");
который, оказывается, является изображением, даже jpeg-изображением, я хотел бы, чтобы конструктор данных вызывал конструктор изображения, который, в свою очередь, вызывает конструктор jpgimage.
Я не могу заставить его работать, и люди предупреждают о разрезании, виртуальных конструкторах и т.д. Но разве такой странный способ настроить его?
Наследование должно использоваться для отношений. Таким образом, image<T>
представляет собой data<T>
, но не наоборот. Нет смысла вызывать метод, специфичный для image<T>
для объекта data<T>
, который в конце концов может не быть image<T>
. Тот факт, что вы хотите это сделать, показывает, что ваш дизайн кода ошибочен. Переосмыслите свой код.
Чтобы реализовать это, вам нужны данные, чтобы быть владельцем реализации, а не базовым классом:
template<typename T>
class base_data {
base_data ( string s ) {} // loads from file
// ...
};
template<typename T>
class image: public base_data <T> {
image ( string s ) {} // loads from file
...
};
template<typename T>
class jpgimage : public image<T> {
jpgimage ( string s ) {} // loads from file
// ...
// other image types
};
template<typename T>
class data {
data ( string s ) {
if(is_jpeg( s )) impl = new jpeg_data<T>( s );
// ...
} // loads from file
// ...
private:
base_data<T> *impl;
};
Теперь в конструкторе вы можете создать правильный тип реализации и так далее.
Я бы сказал, что это плохой дизайн. Вам не нужно работать с общими классами data
чтобы угадать, работаете ли вы с изображениями, если вы точно знаете, что делаете. Используйте класс image
или jpgimage
где он вам нужен, и сделайте все остальное работать с общим классом data
.
image
и jpgimage
должны быть только методами данных.
image<int> im1("lena.jpg");
иimage<int> im2("lena.png");
(с другим конструктором для изображений PNG), а затем используйте их как объекты одного и того же класса. Таким образом, изображение в формате JPEG - это изображение, а изображение в формате PNG - это изображение, но я хочу использовать только тот факт, что они оба являются изображениями после их загрузки. В этом случае лучше кодировать разные параметры ввода-вывода как методы, а не разные классы, включая специфичные для типа файла части, такие как заголовки и т. Д. - именно поэтому я думал, что для разных классов будет лучше.