конструкторы, вызывающие подкласс

У меня есть (частично реализованная) иерархия классов, где

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.

Я никак не могу заставить его работать, и люди предупреждают о нарезке, виртуальных конструкторах и т. д. Но неужели это такой странный способ настройки?


person alle_meije    schedule 15.10.2013    source источник
comment
это не С++. Вы должны сделать каждый класс template   -  person Walter    schedule 16.10.2013
comment
То, что вы хотите, это Data Factory. Вы передаете фабрике имя файла. Он определяет, какой тип объекта создать, и возвращает его.   -  person Martin York    schedule 16.10.2013
comment
В главе 8 Modern C++ Design Александреску обсуждает Заводской узор.   -  person TemplateRex    schedule 19.10.2013


Ответы (3)


Наследование должно использоваться для отношений is a. Таким образом, image<T> является data<T>, но не наоборот! Нет смысла вызывать метод, специфичный для image<T>, для объекта data<T>, который в конце концов может не быть image<T>. Тот факт, что вы хотите это сделать, показывает, что дизайн вашего кода ошибочен. Переосмыслите дизайн своего кода.

person Walter    schedule 15.10.2013
comment
Дело принято. Я хотел закодировать его так, чтобы, например, я мог загружать image<int> im1("lena.jpg"); и image<int> im2("lena.png"); (с другим конструктором для изображений PNG), а затем использовать их как объекты одного класса. Таким образом, изображение в формате jpeg является изображением, а изображение png является изображением, но я хочу использовать только тот факт, что они оба являются изображениями после их загрузки. В этом случае лучше кодировать различные параметры ввода-вывода как методы, а не как разные классы, включая части, специфичные для типа файла, такие как заголовки и т. д. - я думал, что для этого лучше всего подходят разные классы. - person alle_meije; 16.10.2013
comment
Я точно знаю, откуда вы пришли. Но лучше подумать об этом самой! - person Walter; 16.10.2013

Чтобы реализовать это, вам понадобятся данные, которые будут владельцем реализации, а не базового класса:

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;
};

Теперь в конструкторе вы можете создать правильный тип реализации и так далее.

person Slava    schedule 15.10.2013
comment
Спасибо за это. Тот факт, что для этого требуется другой класс, уже показывает, что это не очень хорошая идея... - person alle_meije; 16.10.2013

Я бы сказал, что это плохой дизайн. Вам не нужно работать с общими data классами только для того, чтобы угадать, работаете ли вы с изображениями, если вы точно знаете, что работаете. Используйте класс image или jpgimage там, где вам это нужно, и заставьте все остальное работать с общим классом data.

person Avidan Borisov    schedule 15.10.2013
comment
Я сделал код более кратким, потому что в идеале я хочу что-то, что работает с различными формами числовых данных, может быть изображениями, поверхностями, сигналами и т. д. Я думаю, что классы image и jpgimage должны действительно быть только методами данных. - person alle_meije; 16.10.2013